

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="Blue~u~u~u">
  <meta name="author" content="Blue~u~u~u">
  <meta name="keywords" content="">
  <meta name="description" content="RabbitMQ1. 消息中间件概述1.1.为什么学习消息队列电子商务应用中，经常需要对庞大的海量数据进行监控，随着网络技术和软件开发技术的不断提高，在实战开发中MQ的使用与日俱增，特别是RabbitMQ在分布式系统中存储转发消息，可以保证数据不丢失，也能保证高可用性，即集群部署的时候部分机器宕机可以继续运行。在大型电子商务类网站，如京东、淘宝、去哪儿等网站有着深入的应用 。 队列的主要作用是消除">
<meta property="og:type" content="article">
<meta property="og:title" content="RabbitMQ学习笔记">
<meta property="og:url" content="http://www.slx.blue/2022/02/28/RabbitMQ%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="Blue~u~u~u~u">
<meta property="og:description" content="RabbitMQ1. 消息中间件概述1.1.为什么学习消息队列电子商务应用中，经常需要对庞大的海量数据进行监控，随着网络技术和软件开发技术的不断提高，在实战开发中MQ的使用与日俱增，特别是RabbitMQ在分布式系统中存储转发消息，可以保证数据不丢失，也能保证高可用性，即集群部署的时候部分机器宕机可以继续运行。在大型电子商务类网站，如京东、淘宝、去哪儿等网站有着深入的应用 。 队列的主要作用是消除">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image002.jpg?versionId=CAEQKRiBgMC2j6yA.hciIGJjZDdmNjk3M2UyMjRjMWJiMDhmY2MyZWU2ZTVkYWE0">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image004.gif?versionId=CAEQKRiBgMC8j6yA.hciIGNiNGQzN2ViZDIzMjQ1NGU5OGJhNGEzZDVlMTlhNDVi">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image006.gif?versionId=CAEQKRiBgIC6j6yA.hciIDgyNDI3OTMyMTc3ZDRiNjlhZWU1ODRhNDY1MjM1NzAw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image008.gif?versionId=CAEQKRiBgIC1jayA.hciIGFlNDFlNWIwYmRhMTQzMDY4NGE4OTI0MDA0OGQzODcx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image010.gif?versionId=CAEQKRiBgMChjayA.hciIDY5MDg0MTU1MTEwZjQ1MWY5MWMyOTg3ZTFjOWQ0Yzg5">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image012.gif?versionId=CAEQKRiBgMCrjayA.hciIDRhNjU3ODM4ZjlkZDRiY2U5MGI2ZjFlMzgxMDhkYzVh">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image014.gif?versionId=CAEQKRiBgMCYjayA.hciIGVkMjk0MTQxMTNlNDQ4ZGQ4ZjRiOGQxODc2MGYwZjkz">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image016.gif?versionId=CAEQKRiBgMD6jKyA.hciIGUwNTQxZWU4MTA0YTRkNDg4OTE5YjJmMjhjNmE1Yzli">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image018.gif?versionId=CAEQKRiBgMCnjayA.hciIDU3MmEwOGViZWE3NDQ1OWRiMjIwNDM4YzdiNDZlZGY2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image020.gif?versionId=CAEQKRiBgMDvjKyA.hciIGE0NTdjYjBmY2Q5YTQ5NDJhN2UzMTQzODFmMGNhMzc2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image022.gif?versionId=CAEQKRiBgICli6yA.hciIDI1ZTY3MmFlOGM0NjRhZDFhYWFlNzgxNmEwOTk1NTUw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image024.gif?versionId=CAEQKRiBgIChi6yA.hciIDFiMzI2OGM5Nzc3MjQ5ODRiZmUyMDdmNjEzMmYzMjY3">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image026.jpg?versionId=CAEQKRiBgICWi6yA.hciIDdlZTA3ZGE3N2RhNzRjZDViYjk1Yzk4MGEwNDljNTZk">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clib_image100.png?versionId=CAEQKRiCgMDBj6yA.hciIGIyODhlNzI2ZGQ4ZDRhNDA5OWQyNjgxZGRkYzUzMzI4">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image030.png?versionId=CAEQKRiBgICOi6yA.hciIDNjYTFmMGE1YjM2MTQyOTlhZjYxZGY5YmFmMzBkNjA4">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image040.png?versionId=CAEQKRiBgMCmiayA.hciIDMyM2NlZmIwODdhODRjMTQ5NzE5NGEyMzI5YTg1MjQw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image042.gif?versionId=CAEQKRiBgICiiayA.hciIDI3ODhiYWIxYmNlNDQ1MTE4NzI3NmRhYWUyYmEwNWJk">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image044.gif?versionId=CAEQKRiBgICfiayA.hciIGU0NmE4NjQ0NDUxYjQ5OTk5NTVjZWM0ZjgzYzM0YjVh">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image046.gif?versionId=CAEQKRiBgICOiayA.hciIDJlNjQzMWJjMGNkZDRiYzdhMzBmMDY3YWY0N2Q2MDRm">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image048.gif?versionId=CAEQKRiBgMCIiayA.hciIGEwMjZkNzYwNDg0NTQzZTM4YmVmYWQwYzIyNDAzYzIx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image048.gif?versionId=CAEQKRiBgMCIiayA.hciIGEwMjZkNzYwNDg0NTQzZTM4YmVmYWQwYzIyNDAzYzIx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image052.gif?versionId=CAEQKRiCgMCMiayA.hciIGUyYWU3NGExNDQyZDQ3NWFiNThhNTQ4NDNkZDlmNGMx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image054.gif?versionId=CAEQKRiBgMCBiayA.hciIDAyYmE2MWM4ZjliZTQ4ZGI4NWI4ZTgxMGU1MzBlM2Ix">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image056.gif?versionId=CAEQKRiBgMCCiayA.hciIDA5ODUzZDc4N2VhOTQ4MTBiMWFlNGUyMjFhODczZTli">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image058.gif?versionId=CAEQKRiBgMDQiKyA.hciIDRlZWQ5MDExMDQ5MDRiMjdhYjRhMGNhYjA0OWZjN2Y4">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image060.gif?versionId=CAEQKRiBgICZh6yA.hciIGE5MTEwMDU3YjlmNjQxZTY5Yjc0NTAxOGZiMmY0ZTc5">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image062.gif?versionId=CAEQKRiBgMCXh6yA.hciIGRmMjVlZjI2Y2NhNDQwZDNiZTUwNWEzMjNiMjkzNDBm">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image064.jpg?versionId=CAEQKRiBgICKh6yA.hciIDFkMjg4NmMyOGQyMDQ5ZWVhZjdjYTU3MjU3MjMzNjhl">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image066.gif?versionId=CAEQKRiBgICBh6yA.hciIGJiZjEzYTNkMjNjMzRjN2U4MzBlOWJlNGU5MzE3ZmU2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image068.gif?versionId=CAEQKRiBgID1hqyA.hciIDQwNTUzMjRmZmYxYTRlZGU4NTM5ODJkMTg4NWZjZTAw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image070.gif?versionId=CAEQKRiBgID6hqyA.hciIDU2Y2JiNjRjOTMxNTQyOTk5NzY3Njg0YmJiMTdmZjNh">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image072.gif?versionId=CAEQKRiBgIDthqyA.hciIDQ5NGYwZmNlNGM3ODQ4MjM5ZWQwZWQxNmEyMTQ0MjA2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image074.gif?versionId=CAEQKRiBgID0hqyA.hciIDgwMDE3ZGVkODBmNjQwNmVhODNmMDQ0MWJmYWJlZmI4">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image076.gif?versionId=CAEQKRiBgMDthqyA.hciIDY1MmZmZmE5ZjFmZDQzNTA5Mjg2ODUxM2RhZWJlNDE3">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image078.gif?versionId=CAEQKRiBgMDkhqyA.hciIDhmMTBjYWYxOGM5NzQ4MGJiM2RiZWQzOGE5OTBmYzM0">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image080.gif?versionId=CAEQKRiBgMDrhKyA.hciIDFmNzU5MzY5NDRjZTQ5MzhhNjAyODllZjczM2YyZDQ0">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image082.jpg?versionId=CAEQKRiCgMDShKyA.hciIDU4MDljNTQ3MDMyNjQ1ZmNiYTJmODRmZDAzMWU4OGI2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image084.jpg?versionId=CAEQKRiBgMDWhKyA.hciIDYxYTFlZWIxZDU4YzQ1ZjU4M2UzZGM2NDhiMjc0ODBl">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image086.jpg?versionId=CAEQKRiBgMDjhKyA.hciIGIxNzg5OWM4Mjk2OTQxMGI4NjdkOTZlYmE2YzRmZTM3">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image088.jpg?versionId=CAEQKRiBgMDOhKyA.hciIGI5ZjY3ZmZkNWJkNTQwZjU5NmVmZWQxOTU1ZjZlYmNm">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image090.jpg?versionId=CAEQKRiBgIDShKyA.hciIGI0ODgwZTU0ZWJlODRmMGM5NDQxOWY2ODVlYzA3YzZj">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image092.gif?versionId=CAEQKRiBgMCbhKyA.hciIGVhODk4YzBiODc5NjRjNzNhYTYxZDI1ZTgwMjM0N2Y3">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image094.gif?versionId=CAEQKRiBgMCYhKyA.hciIGRmZGNhZTBlNDliZDQ0Yzg4NmRjNWM1NDNlNTg2MTg2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image096.gif?versionId=CAEQKRiBgICRhKyA.hciIDYxMmQyYTg2ZjRmODRkODBhMjFkZGI3MTA4ZDRlNmEy">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image098.gif?versionId=CAEQKRiBgMCShKyA.hciIGFiODYzNTE3NDZjOTRiZDViNTFiZWJhMTkzMDc4OTZk">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image108.gif?versionId=CAEQKRiBgICQgqyA.hciIDkxMWMyMTBlZTk3NjQyYWQ5ZTkyNjI0ZmIwZjk3MmE5">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image110.gif?versionId=CAEQKRiBgMCMgqyA.hciIGM3ZTcxN2Y5YThkZjQ3ODliNjg2ZmQ1YWZkMzBhMWM0">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image112.gif?versionId=CAEQKRiBgMCNgqyA.hciIDk3MjgxMjdiMjJiMzQ4ZWNiYTUzNDYyMzJjYTk5NjFj">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image114.gif?versionId=CAEQKRiBgMCDgqyA.hciIDlkYjUyMDRmZGU3ZDQzODI5NjcyMGEwMzgyZGY2OTcx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image116.gif?versionId=CAEQKRiBgMCCgqyA.hciIDhhMGY2MzNmM2ZhNzRlNGNhZmZkMGYyMzAwMTMyM2Mw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image118.gif?versionId=CAEQKRiBgIDugayA.hciIDdhZTUwODE0OGJjZDQ3NDk4ODgzNjM0ZmZkZWU2NmNk">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image120.gif?versionId=CAEQKRiBgMC9gKyA.hciIDBjZjE5M2Q1NDM2YzQ0OWY4NGVlNmMyZDAyNDI0YTYx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image122.gif?versionId=CAEQKRiBgIC6gKyA.hciIGQ5NzliMWI1ODVmOTRjZDI5OTJhZTY5MDY3YTUzZjk0">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image124.gif?versionId=CAEQKRiBgICpgKyA.hciIGVlZTYwZGYzY2ZjYjQ5ODI5OWVlMWExMTBjODgxZDIw">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image126.gif?versionId=CAEQKRiDgICcgKyA.hciIDY4NzllNTcwM2U0NTRiYjU5NzgwZjIzMjQ0ODMwOWI1">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image128.gif?versionId=CAEQKRiBgICfgKyA.hciIGI4Y2NlNGFmZTNhMDQ5ZjhiZmM2ZGY4YWRhNmIxMGU2">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image130.gif?versionId=CAEQKRiBgMCMgKyA.hciIGU2ZWEyMzM4MGUxMDQ2YmZiMTQxN2FlNDM0MmQzYjlm">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image132.gif?versionId=CAEQKRiBgMCWgKyA.hciIDQ3MjE4NmZiNjE0YzRhMmY4ZjhlNWQ0ZWE1MjBhMmU5">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image134.gif?versionId=CAEQKRiBgMChgKyA.hciIDZhMTI2MDMzOGUyOTQ3ODE4OGUwNWMwZjY3OGRlMzhh">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image136.gif?versionId=CAEQKRiBgICVgKyA.hciIDE4ZWM2ZWJhZTE0MTQ4YWQ4YjI3YjBhZjBkNTAwYjkx">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image138.gif?versionId=CAEQKRiBgMDT_6uA.hciIGMxZDY3N2JmYWE4MTQzYTA5MTMwN2I3NzI2YzJlMWNj">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image140.gif?versionId=CAEQKRiBgMCN_quA.hciIGVhYmVkNmU4NGQ0ZTRhMmRhNDY2YzgzMmE0YzQzY2Yz">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image142.jpg?versionId=CAEQKRiBgMD3_auA.hciIDFhMTNlNjI3MjdjNDQ5ZTlhNmQ1ZWViOThhZDg1ZDdi">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image146.jpg?versionId=CAEQKRiBgMDl_auA.hciIDY4ZDlkNzU4NmUzMzRhMmJiYWM0ZjgwOTc5MTNiYjBj">
<meta property="og:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image148.jpg?versionId=CAEQKRiBgICK_quA.hciIGIyMDJlODgyYjlkNTQwOTQ4YWUxYTYwNjc0MmZkNzc3">
<meta property="article:published_time" content="2022-02-28T11:54:03.000Z">
<meta property="article:modified_time" content="2022-02-28T11:57:19.690Z">
<meta property="article:author" content="Blue~u~u~u">
<meta property="article:tag" content="RabbitMQ">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image002.jpg?versionId=CAEQKRiBgMC2j6yA.hciIGJjZDdmNjk3M2UyMjRjMWJiMDhmY2MyZWU2ZTVkYWE0">
  
  <title>RabbitMQ学习笔记 - Blue~u~u~u~u</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.slx.blue","root":"/","version":"1.8.12","typing":{"enable":true,"typeSpeed":180,"cursorChar":"_","loop":true},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname"}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>

<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"/>
<script src="/live2d-widget/autoload.js"></script>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Blue~u~u</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/images/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="RabbitMQ学习笔记">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2022-02-28 19:54" pubdate>
        2022年2月28日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      67k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      208 分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">RabbitMQ学习笔记</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：3 个月前
                
              </p>
            
            <div class="markdown-body">
              <h1 id="RabbitMQ"><a href="#RabbitMQ" class="headerlink" title="RabbitMQ"></a>RabbitMQ</h1><h1 id="1-消息中间件概述"><a href="#1-消息中间件概述" class="headerlink" title="1. 消息中间件概述"></a>1. 消息中间件概述</h1><h2 id="1-1-为什么学习消息队列"><a href="#1-1-为什么学习消息队列" class="headerlink" title="1.1.为什么学习消息队列"></a>1.1.为什么学习消息队列</h2><p>电子商务应用中，经常需要对庞大的海量数据进行监控，随着网络技术和软件开发技术的不断提高，在实战开发中MQ的使用与日俱增，特别是RabbitMQ在分布式系统中存储转发消息，可以保证数据不丢失，也能保证高可用性，即集群部署的时候部分机器宕机可以继续运行。在大型电子商务类网站，如京东、淘宝、去哪儿等网站有着深入的应用 。</p>
<p>队列的主要作用是<strong>消除高并发访问高峰，加快网站的响应速度</strong>。</p>
<p>在不使用消息队列的情况下，用户的请求数据直接写入数据库，在高并发的情况下，会对数据库造成巨大的压力，同时也使得系统响应延迟加剧。</p>
<h2 id="1-2-什么是消息中间件"><a href="#1-2-什么是消息中间件" class="headerlink" title="1.2.什么是消息中间件"></a>1.2.什么是消息中间件</h2><p>MQ全称为<strong>Message Queue</strong>， 消息队列(MQ)是一种应用程序对应用程序的通信方法。</p>
<p>介绍：消息队列就是基础数据结构中的“先进先出”的一种数据机构。想一下，生活中买东西，需要排队，先排的人先买消费，就是典型的“先进先出”。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image002.jpg?versionId=CAEQKRiBgMC2j6yA.hciIGJjZDdmNjk3M2UyMjRjMWJiMDhmY2MyZWU2ZTVkYWE0" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>消息传递：</strong>指的是程序之间通过消息发送数据进行通信，而不是通过直接调用彼此来通信，直接调用通常是用于诸如远程过程调用的技术。</p>
<p><strong>排队：</strong>指的是应用程序通过队列来通信。</p>
<p><strong>业务场景说明：</strong></p>
<p>消息队列在大型电子商务类网站，如京东、淘宝、去哪儿等网站有着深入的应用，为什么会产生消息队列？有几个原因：</p>
<p>不同进程（process）之间传递消息时，两个进程之间<strong>耦合</strong>程度过高，改动一个进程，引发必须修改另一个进程，为了<strong>隔离</strong>这两个进程，在两进程间抽离出一层（一个模块），所有两进程之间传递的消息，都必须通过消息队列来传递，单独修改某一个进程，不会影响另一个；</p>
<p>不同进程（process）之间传递消息时，为了实现标准化，将消息的格式规范化了，并且，某一个进程接受的<strong>消息太多</strong>，一下子无法处理完，并且也有先后顺序，必须对收到的消息<strong>进行排队</strong>，因此诞生了事实上的消息队列；</p>
<p>在项目中，可将一些无需即时返回且耗时的操作提取出来，进行<strong>异步处理</strong>，而这种异步处理的方式大大的节省了服务器的请求响应时间，从而<strong>提高</strong>了<strong>系统</strong>的<strong>吞吐量</strong>。</p>
<h2 id="1-3-消息队列应用场景"><a href="#1-3-消息队列应用场景" class="headerlink" title="1.3.消息队列应用场景"></a>1.3.消息队列应用场景</h2><p>首先我们先说一下消息中间件的主要的作用：</p>
<p>　　<strong>[1]异步处理</strong></p>
<p>　　<strong>[2]解耦服务</strong></p>
<p>　　<strong>[3]流量削峰</strong></p>
<p>上面的三点是我们使用消息中间件最主要的目的.</p>
<h3 id="1-3-1-应用解耦"><a href="#1-3-1-应用解耦" class="headerlink" title="1.3.1.应用解耦"></a>1.3.1.应用解耦</h3><p><strong>传统模式：</strong></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image004.gif?versionId=CAEQKRiBgMC8j6yA.hciIGNiNGQzN2ViZDIzMjQ1NGU5OGJhNGEzZDVlMTlhNDVi" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>传统模式的缺点：</strong></p>
<ul>
<li>系统间耦合性太强，如上图所示，系统A在代码中直接调用系统B和系统C的代码，如果将来D系统接入，系统A还需要修改代码，过于麻烦！</li>
</ul>
<p><strong>中间件模式：</strong></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image006.gif?versionId=CAEQKRiBgIC6j6yA.hciIDgyNDI3OTMyMTc3ZDRiNjlhZWU1ODRhNDY1MjM1NzAw" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>中间件模式的的优点：</strong></p>
<ul>
<li>将消息写入消息队列，需要消息的系统自己从消息队列中订阅，从而系统A不需要做任何修改。</li>
</ul>
<h3 id="1-3-2-异步处理"><a href="#1-3-2-异步处理" class="headerlink" title="1.3.2.异步处理"></a>1.3.2.异步处理</h3><p>场景说明：用户注册后，需要发注册邮件和注册短信，传统的做法有两种</p>
<p>l 串行的方式</p>
<p>l 并行的方式</p>
<p><strong>(1)</strong> <strong>串行方式：</strong></p>
<p>将注册信息写入数据库后，发送注册邮件，再发送注册短信，以上三个任务全部完成后才返回给客户端。 这有一个问题是，邮件，短信并不是必须的，它只是一个通知，而这种做法让客户端等待没有必要等待的东西。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image008.gif?versionId=CAEQKRiBgIC1jayA.hciIGFlNDFlNWIwYmRhMTQzMDY4NGE4OTI0MDA0OGQzODcx" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>(2)</strong> <strong>并行方式：</strong></p>
<p>将注册信息写入数据库后，发送邮件的同时，发送短信，以上三个任务完成后，返回给客户端，并行的方式能提高处理的时间。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image010.gif?versionId=CAEQKRiBgMChjayA.hciIDY5MDg0MTU1MTEwZjQ1MWY5MWMyOTg3ZTFjOWQ0Yzg5" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>假设三个业务节点分别使用50ms，串行方式使用时间150ms，并行使用时间100ms。虽然并行已经提高了处理时间，但是，前面说过，邮件和短信对我正常的使用网站没有任何影响，客户端没有必要等着其发送完成才显示注册成功，应该是写入数据库后就返回.</p>
<p>**(3)**<strong>消息队列</strong><br> 引入消息队列后，把发送邮件，短信不是必须的业务逻辑异步处理</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image012.gif?versionId=CAEQKRiBgMCrjayA.hciIDRhNjU3ODM4ZjlkZDRiY2U5MGI2ZjFlMzgxMDhkYzVh" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>由此可以看出，引入消息队列后，用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计)，</p>
<p>引入消息队列后处理后，响应时间是串行的3分之1，是并行的2分之1。</p>
<p><strong>传统模式的缺点：</strong></p>
<ul>
<li>一些非必要的业务逻辑以同步的方式运行，太耗费时间。</li>
</ul>
<p><strong>中间件模式的的优点：</strong></p>
<ul>
<li>将消息写入消息队列，非必要的业务逻辑以异步的方式运行，加快响应速度</li>
</ul>
<h3 id="1-3-3-流量削峰"><a href="#1-3-3-流量削峰" class="headerlink" title="1.3.3.流量削峰"></a>1.3.3.流量削峰</h3><p>流量削峰一般在秒杀活动中应用广泛</p>
<p><strong>场景：</strong> 秒杀活动，一般会因为流量过大，导致应用挂掉，为了解决这个问题，一般在应用前端加入消息队列。</p>
<p><strong>传统模式</strong></p>
<p>如订单系统，在下单的时候就会往数据库写数据。但是数据库只能支撑每秒1000左右的并发写入，并发量再高就容易宕机。低峰期的时候并发也就100多个，但是在高峰期时候，并发量会突然激增到5000以上，这个时候数据库肯定卡死了。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image014.gif?versionId=CAEQKRiBgMCYjayA.hciIGVkMjk0MTQxMTNlNDQ4ZGQ4ZjRiOGQxODc2MGYwZjkz" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>传统模式的缺点：</strong></p>
<ul>
<li>并发量大的时候，所有的请求直接怼到数据库，造成数据库连接异常</li>
</ul>
<p><strong>中间件模式：</strong></p>
<p>消息被MQ保存起来了，然后系统就可以按照自己的消费能力来消费，比如每秒1000个数据，这样慢慢写入数据库，这样就不会卡死数据库了。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image016.gif?versionId=CAEQKRiBgMD6jKyA.hciIGUwNTQxZWU4MTA0YTRkNDg4OTE5YjJmMjhjNmE1Yzli" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>中间件模式的的优点：</strong></p>
<p>系统A慢慢的按照数据库能处理的并发量，从消息队列中慢慢拉取消息。在生产中，这个短暂的高峰期积压是允许的。</p>
<p>流量削峰也叫做削峰填谷</p>
<p>使用了MQ之后，限制消费消息的速度为1000，但是这样一来，高峰期产生的数据势必会被积压在MQ中，高峰就被“削”掉了。但是因为消息积压，在高峰期过后的一段时间内，消费消息的速度还是会维持在 3消费完积压的消息，这就叫做“填谷”</p>
<h3 id="1-3-4-什么是QPS，PV"><a href="#1-3-4-什么是QPS，PV" class="headerlink" title="1.3.4.什么是QPS，PV"></a>1.3.4.什么是QPS，PV</h3><p>QPS即每秒查询率，是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。</p>
<p>每秒查询率</p>
<p>因特网上，经常用每秒查询率来衡量域名系统服务器的机器的性能，即为QPS。</p>
<p>或者理解：每秒的响应请求数，也即是最大吞吐能力。</p>
<p>计算关系：</p>
<p>QPS = 并发量 / 平均响应时间</p>
<p>并发量 = QPS * 平均响应时间</p>
<p>原理：每天80%的访问集中在20%的时间里，这20%时间叫做峰值时间。</p>
<p>公式：( 总PV数 * 80% ) / ( 每天秒数 * 20% ) = 峰值时间每秒请求数(QPS) 。</p>
<p>机器：峰值时间每秒QPS / 单台机器的QPS = 需要的机器 。</p>
<h3 id="1-3-5-什么是PV-，-UV-，-PR"><a href="#1-3-5-什么是PV-，-UV-，-PR" class="headerlink" title="1.3.5.什么是PV ， UV ， PR"></a>1.3.5.什么是PV ， UV ， PR</h3><p>① 什么是pv　　</p>
<p>**PV(page view)**，即页面浏览量，或点击量；通常是衡量一个网络新闻频道或网站甚至一条网络新闻的主要指标。</p>
<p>对pv的解释是，一个访问者在24小时(0点到24点)内到底看了你网站几个页面。这里需要强调：同一个人浏览你网站同一个页面，不重复计算pv量，点100次也算1次。说白了，pv就是一个访问者打开了你的几个页面。</p>
<p>PV之于网站，就像收视率之于电视，从某种程度上已成为投资者衡量商业网站表现的最重要尺度。</p>
<p>pv的计算：当一个访问者访问的时候，记录他所访问的页面和对应的IP，然后确定这个IP今天访问了这个页面没有。如果你的网站到了23点，单纯IP有60万条的话，每个访问者平均访问了3个页面，那么pv表的记录就要有180万条。</p>
<p>② 什么是uv<br> **uv(unique visitor)**，指访问某个站点或点击某条新闻的不同IP地址的人数。</p>
<p>在同一天内，uv只记录第一次进入网站的具有独立IP的访问者，在同一天内再次访问该网站则不计数。独立IP访问者提供了一定时间内不同观众数量的统计指标，而没有反应出网站的全面活动。</p>
<p>③ 什么是ＰＲ值<br> 　PR值，即<strong>PageRank</strong>，网页的级别技术，用来标识网页的等级/重要性。级别从1到10级，10级为满分。PR值越高说明该网页越受欢迎（越重要）。</p>
<p>　　例如：一个PR值为1的网站表明这个网站不太具有流行度，而PR值为7到10则表明这个网站非常受欢迎（或者说极其重要）。</p>
<h2 id="1-4-AMQP-和-JMS"><a href="#1-4-AMQP-和-JMS" class="headerlink" title="1.4. AMQP 和 JMS"></a>1.4. AMQP 和 JMS</h2><p>MQ是消息通信的模型；实现MQ的大致有两种主流方式：AMQP、JMS。</p>
<h3 id="1-4-1-AMQP"><a href="#1-4-1-AMQP" class="headerlink" title="1.4.1. AMQP"></a>1.4.1. AMQP</h3><p>AMQP是一种<strong>高级消息队列协议（<strong><strong>Advanced Message Queuing Protocol</strong></strong>）</strong>，更准确的说是一种binary wire-level protocol（<strong>链接协议</strong>）。这是其和JMS的本质差别，AMQP不从API层进行限定，而是直接定义网络交换的数据格式。</p>
<h3 id="1-4-2-JMS"><a href="#1-4-2-JMS" class="headerlink" title="1.4.2. JMS"></a>1.4.2. JMS</h3><p>JMS即<strong>Java消息服务（JavaMessage Service）</strong>应用程序接口，是一个Java平台中关于面向消息中间件（MOM）的API，用于在两个应用程序之间，或分布式系统中发送消息，进行异步通信。</p>
<h3 id="1-4-3-AMQP-与-JMS-区别"><a href="#1-4-3-AMQP-与-JMS-区别" class="headerlink" title="1.4.3. AMQP 与 JMS 区别"></a>1.4.3. AMQP 与 JMS 区别</h3><ul>
<li>JMS是定义了统一的接口，来对消息操作进行统一；AMQP是通过规定协议来统一数据交互的格式</li>
<li>JMS限定了必须使用Java语言；AMQP只是协议，不规定实现方式，因此是跨语言的。</li>
<li>JMS规定了两种消息模式；而AMQP的消息模式更加丰富</li>
</ul>
<h2 id="1-5-消息队列产品"><a href="#1-5-消息队列产品" class="headerlink" title="1.5. 消息队列产品"></a>1.5. 消息队列产品</h2><p>市场上常见的消息队列有如下：</p>
<ul>
<li>ActiveMQ：基于JMS</li>
<li>ZeroMQ：基于C语言开发</li>
<li>Rabbitmq:基于AMQP协议，erlang语言开发，稳定性好</li>
<li>RocketMQ：基于JMS，阿里巴巴产品</li>
<li>Kafka：类似MQ的产品；分布式消息系统，高吞吐量</li>
</ul>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image018.gif?versionId=CAEQKRiBgMCnjayA.hciIDU3MmEwOGViZWE3NDQ1OWRiMjIwNDM4YzdiNDZlZGY2" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>1.ActiveMQ </p>
<p>​    优点：单机吞吐量万级，时效性 ms 级，可用性高，基于主从架构实现高可用性，消息可靠性较 低的概率丢失数据 缺点:官方社区现在对 ActiveMQ 5.x 维护越来越少，高吞吐量场景较少使用。 </p>
<p>2.Kafka </p>
<p>​    大数据的杀手锏，谈到大数据领域内的消息传输，则绕不开 Kafka，这款为大数据而生的消息中间件， 以其百万级 TPS 的吞吐量名声大噪，迅速成为大数据领域的宠儿，在数据采集、传输、存储的过程中发挥 着举足轻重的作用。目前已经被 LinkedIn，Uber, Twitter, Netflix 等大公司所采纳。 优点: 性能卓越，单机写入 TPS 约在百万条/秒，最大的优点，就是吞吐量高。时效性 ms 级可用性非 常高，kafka 是分布式的，一个数据多个副本，少数机器宕机，不会丢失数据，不会导致不可用,消费者采 用 Pull 方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;有优秀的第三方 Kafka Web 管理界面 Kafka-Manager；在日志领域比较成熟，被多家公司和多个开源项目使用；功能支持： 功能较为简单，主要支持简单的 MQ 功能，在大数据领域的实时计算以及日志采集被大规模使用 缺点：Kafka 单机超过 64 个队列/分区，Load 会发生明显的飙高现象，队列越多，load 越高，发送消 息响应时间变长，使用短轮询方式，实时性取决于轮询间隔时间，消费失败不支持重试；支持消息顺序， 但是一台代理宕机后，就会产生消息乱序，社区更新较慢；</p>
<p> 3.RocketMQ </p>
<p>​    RocketMQ 出自阿里巴巴的开源产品，用 Java 语言实现，在设计时参考了 Kafka，并做出了自己的一 些改进。被阿里巴巴广泛应用在订单，交易，充值，流计算，消息推送，日志流式处理，binglog 分发等场 景。 优点:单机吞吐量十万级,可用性非常高，分布式架构,消息可以做到 0 丢失,MQ 功能较为完善，还是分 布式的，扩展性好,支持 10 亿级别的消息堆积，不会因为堆积导致性能下降,源码是 java 我们可以自己阅 读源码，定制自己公司的 MQ 缺点：支持的客户端语言不多，目前是 java 及 c++，其中 c++不成熟；社区活跃度一般,没有在 MQ 核心中去实现 JMS 等接口,有些系统要迁移需要修改大量代码 </p>
<p>4.RabbitMQ </p>
<p>​    2007 年发布，是一个在 AMQP(高级消息队列协议)基础上完成的，可复用的企业消息系统，是当前最 主流的消息中间件之一。 优点:由于 erlang 语言的高并发特性，性能较好；吞吐量到万级，MQ 功能比较完备,健壮、稳定、易 用、跨平台、支持多种语言 如：Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP 等，支持 AJAX 文档齐全；开源提供的管理界面非常棒，用起来很好用,社区活跃度高；更新频率相当高 <a target="_blank" rel="noopener" href="https://www.rabbitmq.com/news.html">https://www.rabbitmq.com/news.html</a> </p>
<p>缺点：商业版需要收费,学习成本较高</p>
<h3 id="1-5-1-MQ-的选择"><a href="#1-5-1-MQ-的选择" class="headerlink" title="1.5.1.MQ 的选择"></a>1.5.1.MQ 的选择</h3><p>1.Kafka Kafka 主要特点是基于 Pull 的模式来处理消息消费，追求高吞吐量，一开始的目的就是用于日志收集 和传输，适合产生大量数据的互联网服务的数据收集业务。大型公司建议可以选用，如果有日志采集功能， 肯定是首选 kafka 了。</p>
<p>2.RocketMQ 天生为金融互联网领域而生，对于可靠性要求很高的场景，尤其是电商里面的订单扣款，以及业务削 峰，在大量交易涌入时，后端可能无法及时处理的情况。RoketMQ 在稳定性上可能更值得信赖，这些业务 场景在阿里双 11 已经经历了多次考验，如果你的业务有上述并发场景，建议可以选择 RocketMQ。 </p>
<p>3.RabbitMQ 结合 erlang 语言本身的并发优势，性能好时效性微秒级，社区活跃度也比较高，管理界面用起来十分 方便，如果你的数据量没有那么大，中小型公司优先选择功能比较完备的 RabbitMQ。</p>
<h2 id="1-6-RabbitMQ"><a href="#1-6-RabbitMQ" class="headerlink" title="1.6. RabbitMQ"></a>1.6. RabbitMQ</h2><p>RabbitMQ是由erlang语言开发，基于AMQP（Advanced Message Queue 高级消息队列协议）协议实现的消息队列，它是一种应用程序之间的通信方法，消息队列在分布式系统开发中应用非常广泛。</p>
<p>RabbitMQ官方地址：<a target="_blank" rel="noopener" href="http://www.rabbitmq.com/">http://www.rabbitmq.com/</a> </p>
<p>RabbitMQ提供了<strong>6****种模式</strong>：简单模式，work模式 ，Publish/Subscribe发布与订阅模式，Routing路由模式，Topics主题模式，RPC远程调用模式（远程调用，不太算MQ；暂不作介绍）；</p>
<p>官网对应模式介绍：<a target="_blank" rel="noopener" href="https://www.rabbitmq.com/getstarted.html">https://www.rabbitmq.com/getstarted.html</a> </p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image020.gif?versionId=CAEQKRiBgMDvjKyA.hciIGE0NTdjYjBmY2Q5YTQ5NDJhN2UzMTQzODFmMGNhMzc2" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="1-6-1-RabbitMQ简介"><a href="#1-6-1-RabbitMQ简介" class="headerlink" title="1.6.1 RabbitMQ简介"></a>1.6.1 <strong>RabbitMQ</strong>简介</h3><p>AMQP，即 Advanced<br> Message Queuing Protocol（高级消息队列协议），是一个网络协议，是应用层协议的一个开放标准，为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息，并不受客户端/中间件不同产品，不同的开发语言等条件的限制。2006年，AMQP 规范发布。类比HTTP。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image022.gif?versionId=CAEQKRiBgICli6yA.hciIDI1ZTY3MmFlOGM0NjRhZDFhYWFlNzgxNmEwOTk1NTUw" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>2007年，Rabbit 技术公司基于 AMQP 标准开发的 RabbitMQ 1.0 发布。RabbitMQ 采用 Erlang 语言开发。Erlang 语言由 Ericson 设计，专门为开发高并发和分布式系统的一种语言，在电信领域使用广泛。</p>
<p>RabbitMQ 基础架构如下图：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image024.gif?versionId=CAEQKRiBgIChi6yA.hciIDFiMzI2OGM5Nzc3MjQ5ODRiZmUyMDdmNjEzMmYzMjY3" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="1-6-2-RabbitMQ-中的相关概念"><a href="#1-6-2-RabbitMQ-中的相关概念" class="headerlink" title="1.6.2 RabbitMQ 中的相关概念"></a>1.6.2 RabbitMQ 中的相关概念</h3><p>Broker：接收和分发消息的应用，RabbitMQ Server就是 Message Broker</p>
<p>Virtual host:出于多租户和安全因素设计的，把 AMQP 的基本组件划分到一个虚拟的分组中，类似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时，可以划分出多个vhost，每个用户在自己的 vhost 创建 exchange／queue 等</p>
<p>Connection：publisher／consumer 和 broker 之间的 TCP 连接</p>
<p>Channel：如果每一次访问 RabbitMQ 都建立一个 Connection，在消息量大的时候建立 TCP Connection的开销将是巨大的，效率也较低。Channel 是在 connection 内部建立的逻辑连接，如果应用程序支持多线程，通常每个thread创建单独的 channel 进行通讯，AMQP method 包含了channel id 帮助客户端和message broker 识别 channel，所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销</p>
<p>Exchange：message 到达 broker 的第一站，根据分发规则，匹配查询表中的 routing key，分发消息到queue 中去。常用的类型有：**direct (point-to-point)**， <strong>topic (publish-subscribe)</strong> and <strong>fanout (multicast)</strong></p>
<p>Queue：存储消息的容器，消息最终被送到这里，等待 consumer 取走</p>
<p>Binding：exchange 和 queue 之间的虚拟连接，binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中，用于 message 的分发依据</p>
<h1 id="2-安装及配置RabbitMQ"><a href="#2-安装及配置RabbitMQ" class="headerlink" title="2. 安装及配置RabbitMQ"></a>2. 安装及配置RabbitMQ</h1><h2 id="2-1-下载和安装"><a href="#2-1-下载和安装" class="headerlink" title="2.1. 下载和安装"></a>2.1. 下载和安装</h2><h3 id="2-1-1-下载"><a href="#2-1-1-下载" class="headerlink" title="2.1.1. 下载"></a>2.1.1. 下载</h3><p><strong>1.下载Erlang的rpm包</strong></p>
<p>RabbitMQ是Erlang语言编写，所以Erang环境必须要有，注：Erlang环境一定要与RabbitMQ版本匹配：</p>
<p><a target="_blank" rel="noopener" href="https://www.rabbitmq.com/which-erlang.html">https://www.rabbitmq.com/which-erlang.html</a> </p>
<p><strong>2.下载socat的rpm包</strong></p>
<p>rabbitmq安装依赖于socat，所以需要下载socat。</p>
<p>socat下载地址：<a target="_blank" rel="noopener" href="http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm">http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm</a></p>
<p>**3.<strong>下载RabbitMQ的rpm包</strong></p>
<p>RabbitMQ下载地址：<a target="_blank" rel="noopener" href="https://www.rabbitmq.com/download.html%EF%BC%88%E6%A0%B9%E6%8D%AE%E8%87%AA%E8%BA%AB%E9%9C%80%E6%B1%82%E5%8F%8A%E5%8C%B9%E9%85%8D%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%B8%8B%E8%BD%BD%E5%AF%B9%E5%BA%94rpm%E5%8C%85%EF%BC%89rabbitmq-server-3.8.1-1.el7.noarch.rpm">https://www.rabbitmq.com/download.html（根据自身需求及匹配关系，下载对应rpm包）rabbitmq-server-3.8.1-1.el7.noarch.rpm</a></p>
<p>也可从github等网站下载。<a target="_blank" rel="noopener" href="https://hub.fastgit.org/rabbitmq/rabbitmq-server/releases/">https://hub.fastgit.org/rabbitmq/rabbitmq-server/releases/</a></p>
<h3 id="2-1-2-安装"><a href="#2-1-2-安装" class="headerlink" title="2.1.2. 安装"></a>2.1.2. 安装</h3><h4 id="1-安装Erlang、Socat、RabbitMQ"><a href="#1-安装Erlang、Socat、RabbitMQ" class="headerlink" title="1.安装Erlang、Socat、RabbitMQ"></a>1.安装Erlang、Socat、RabbitMQ</h4><p><strong>①rpm -ivh</strong> <strong>erlang-21.3.8.9-1.el7.x86_64.rpm</strong></p>
<p><strong>②rpm -ivh</strong> <strong>socat-1.7.3.2-1.el6.lux.x86_64.rpm</strong></p>
<p>在安装rabbitmq之前需要先安装socat，否则，报错。</p>
<p>可以采用yum安装方式：yum install socat，我们这里采用rpm安装方式</p>
<p><strong>③rpm -ivh</strong> <strong>rabbitmq-server-3.8.1-1.el7.noarch.rpm</strong> </p>
<p>/usr/lib/rabbitmq/bin/ </p>
<h4 id="2-启用管理插件"><a href="#2-启用管理插件" class="headerlink" title="2.启用管理插件"></a>2.启用管理插件</h4><p>rabbitmq-plugins enable rabbitmq_management</p>
<h4 id="3-启动RabbitMQ"><a href="#3-启动RabbitMQ" class="headerlink" title="3.启动RabbitMQ"></a>3.启动RabbitMQ</h4><p>systemctl start rabbitmq-server.service</p>
<p>systemctl status rabbitmq-server.service</p>
<p>systemctl restart rabbitmq-server.service</p>
<p>systemctl stop rabbitmq-server.service </p>
<h4 id="4-查看进程"><a href="#4-查看进程" class="headerlink" title="4.查看进程"></a>4.查看进程</h4><p>ps -ef | grep rabbitmq</p>
<h3 id="2-1-3-测试"><a href="#2-1-3-测试" class="headerlink" title="2.1.3. 测试"></a>2.1.3. 测试</h3><p>o  关闭防火墙：systemctl stop firewalld.service</p>
<p>o  在web浏览器中输入地址：http://虚拟机ip:15672/</p>
<p>o  输入默认账号密码： guest ： guest，guest用户默认不允许远程连接。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image026.jpg?versionId=CAEQKRiBgICWi6yA.hciIDdlZTA3ZGE3N2RhNzRjZDViYjk1Yzk4MGEwNDljNTZk" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>增加自定义账号</strong></p>
<p>l 添加管理员账号密码：rabbitmqctl add_user admin admin</p>
<p>l 分配账号角色：rabbitmqctl set_user_tags admin administrator</p>
<p>l 修改密码：rabbitmqctl change_password admin 123456</p>
<p>l 查看用户列表：rabbitmqctl list_users</p>
<p>使用新账号登录，成功界面</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clib_image100.png?versionId=CAEQKRiCgMDBj6yA.hciIGIyODhlNzI2ZGQ4ZDRhNDA5OWQyNjgxZGRkYzUzMzI4" srcset="/img/loading.gif" lazyload alt="image-20220228182152408"></p>
<p><strong>管理界面标签页介绍</strong></p>
<p>l overview：概览</p>
<p>l connections：无论生产者还是消费者，都需要与RabbitMQ建立连接后才可以完成消息的生产和消费，在这里可以查看连接情况</p>
<p>l channels：通道，建立连接后，会形成通道，消息的投递获取依赖通道。</p>
<p>l Exchanges：交换机，用来实现消息的路由</p>
<p>l Queues：队列，即消息队列，消息存放在队列中，等待消费，消费后被移除队列。</p>
<p><strong>端口：</strong></p>
<p>l 5672：rabbitMq的编程语言客户端连接端口</p>
<p>l 15672：rabbitMq管理界面端口</p>
<p>l 25672：rabbitMq集群的端口</p>
<h3 id="2-1-4-卸载"><a href="#2-1-4-卸载" class="headerlink" title="2.1.4. 卸载"></a>2.1.4. 卸载</h3><p>l rpm -qa | grep rabbitmq</p>
<p>l rpm -e rabbitmq-server</p>
<h2 id="2-2-管理界面"><a href="#2-2-管理界面" class="headerlink" title="2.2. 管理界面"></a>2.2. 管理界面</h2><h3 id="2-2-1-添加用户"><a href="#2-2-1-添加用户" class="headerlink" title="2.2.1. 添加用户"></a>2.2.1. 添加用户</h3><p>如果不使用guest，我们也可以自己创建一个用户：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image030.png?versionId=CAEQKRiBgICOi6yA.hciIDNjYTFmMGE1YjM2MTQyOTlhZjYxZGY5YmFmMzBkNjA4" srcset="/img/loading.gif" lazyload alt="image-20220228182857879"></p>
<p>1、 超级管理员(administrator)</p>
<p>可登录管理控制台，可查看所有的信息，并且可以对用户，策略(policy)进行操作。</p>
<p>2、 监控者(monitoring)</p>
<p>可登录管理控制台，同时可以查看rabbitmq节点的相关信息(进程数，内存使用情况，磁盘使用情况等)</p>
<p>3、 策略制定者(policymaker)</p>
<p>可登录管理控制台， 同时可以对policy进行管理。但无法查看节点的相关信息。</p>
<p>4、 普通管理者(management)</p>
<p>仅可登录管理控制台，无法看到节点信息，也无法对策略进行管理。</p>
<p>5、 其他</p>
<p>无法登录管理控制台，通常就是普通的生产者和消费者。</p>
<h1 id="3-RabbitMQ入门"><a href="#3-RabbitMQ入门" class="headerlink" title="3. RabbitMQ入门"></a>3. RabbitMQ入门</h1><p>官网： <a target="_blank" rel="noopener" href="https://www.rabbitmq.com/%60">https://www.rabbitmq.com/`</a> `</p>
<p>需求：使用简单模式完成消息传递</p>
<p>步骤： </p>
<p>① 创建工程（生成者、消费者）</p>
<p>② 分别添加依赖</p>
<p>③ 编写生产者发送消息</p>
<p>④ 编写消费者接收消息</p>
<h2 id="3-1-搭建示例工程"><a href="#3-1-搭建示例工程" class="headerlink" title="3.1. 搭建示例工程"></a>3.1. 搭建示例工程</h2><h3 id="3-1-1-创建工程"><a href="#3-1-1-创建工程" class="headerlink" title="3.1.1. 创建工程"></a>3.1.1. 创建工程</h3><p>创建项目：<code>rabbitmq-producer</code></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image040.png?versionId=CAEQKRiBgMCmiayA.hciIDMyM2NlZmIwODdhODRjMTQ5NzE5NGEyMzI5YTg1MjQw" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>创建项目：<code>rabbitmq-consumer</code></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image042.gif?versionId=CAEQKRiBgICiiayA.hciIDI3ODhiYWIxYmNlNDQ1MTE4NzI3NmRhYWUyYmEwNWJk" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="3-1-2-添加依赖"><a href="#3-1-2-添加依赖" class="headerlink" title="3.1.2. 添加依赖"></a>3.1.2. 添加依赖</h3><p>往两个rabbitmq的pom.xml文件中添加如下依赖：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.rabbitmq<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>amqp-client<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.6.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br> <br><span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.8.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="3-2-编写生产者"><a href="#3-2-编写生产者" class="headerlink" title="3.2. 编写生产者"></a>3.2. 编写生产者</h2><p>编写消息生产者 <code>com.atguigu.rabbitmq.simple.Producer</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.simple;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.Channel;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Connection;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.ConnectionFactory;<br><span class="hljs-keyword">import</span> java.util.Map;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Producer</span> </span>&#123;<br> <br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        <span class="hljs-comment">//创建连接工厂</span><br>        ConnectionFactory connectionFactory = <span class="hljs-keyword">new</span> ConnectionFactory();<br>        <span class="hljs-comment">//主机地址</span><br>        connectionFactory.setHost(<span class="hljs-string">&quot;192.168.137.118&quot;</span>);<br>        <span class="hljs-comment">//连接端口;默认为 5672</span><br>        connectionFactory.setPort(<span class="hljs-number">5672</span>);<br>        <span class="hljs-comment">//虚拟主机名称;默认为 /</span><br>        connectionFactory.setVirtualHost(<span class="hljs-string">&quot;/&quot;</span>);<br>        <span class="hljs-comment">//连接用户名；默认为guest</span><br>        connectionFactory.setUsername(<span class="hljs-string">&quot;admin&quot;</span>);<br>        <span class="hljs-comment">//连接密码；默认为guest</span><br>        connectionFactory.setPassword(<span class="hljs-string">&quot;123456&quot;</span>);<br> <br>        <span class="hljs-comment">//创建连接</span><br>        Connection connection = connectionFactory.newConnection();<br> <br>        <span class="hljs-comment">//创建频道</span><br>        Channel channel = connection.createChannel();<br> <br>        <span class="hljs-comment">// 声明（创建）队列</span><br>        <span class="hljs-comment">/**</span><br><span class="hljs-comment">         * queue      参数1：队列名称</span><br><span class="hljs-comment">         * durable    参数2：是否定义持久化队列,当mq重启之后,还在</span><br><span class="hljs-comment">         * exclusive  参数3：是否独占本次连接</span><br><span class="hljs-comment">         *            ① 是否独占,只能有一个消费者监听这个队列</span><br><span class="hljs-comment">         *            ② 当connection关闭时,是否删除队列</span><br><span class="hljs-comment">         * autoDelete 参数4：是否在不使用的时候自动删除队列,当没有consumer时,自动删除</span><br><span class="hljs-comment">         * arguments  参数5：队列其它参数</span><br><span class="hljs-comment">         */</span><br>        channel.queueDeclare(<span class="hljs-string">&quot;simple_queue&quot;</span>, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">null</span>);<br> <br>        <span class="hljs-comment">// 要发送的信息</span><br>        String message = <span class="hljs-string">&quot;你好；小兔子！&quot;</span>;<br>        <span class="hljs-comment">/**</span><br><span class="hljs-comment">         * 参数1：交换机名称,如果没有指定则使用默认Default Exchage</span><br><span class="hljs-comment">         * 参数2：路由key,简单模式可以传递队列名称</span><br><span class="hljs-comment">         * 参数3：配置信息</span><br><span class="hljs-comment">         * 参数4：消息内容</span><br><span class="hljs-comment">         */</span><br>        channel.basicPublish(<span class="hljs-string">&quot;&quot;</span>, <span class="hljs-string">&quot;simple_queue&quot;</span>, <span class="hljs-keyword">null</span>, message.getBytes());<br>        System.out.println(<span class="hljs-string">&quot;已发送消息：&quot;</span> + message);<br> <br>        <span class="hljs-comment">// 关闭资源</span><br>        channel.close();<br>        connection.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行程序：<a target="_blank" rel="noopener" href="http://127.0.0.1:15672/">http://192.168.137.118:15672</a><code> </code></p>
<p>在执行上述的消息发送之后；可以登录rabbitMQ的管理控制台,可以发现队列和其消息：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image044.gif?versionId=CAEQKRiBgICfiayA.hciIGU0NmE4NjQ0NDUxYjQ5OTk5NTVjZWM0ZjgzYzM0YjVh" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image046.gif?versionId=CAEQKRiBgICOiayA.hciIDJlNjQzMWJjMGNkZDRiYzdhMzBmMDY3YWY0N2Q2MDRm" srcset="/img/loading.gif" lazyload alt="img"></p>
<h2 id="3-3-编写消费者"><a href="#3-3-编写消费者" class="headerlink" title="3.3. 编写消费者"></a>3.3. 编写消费者</h2><p>编写消息的消费者 <code>com.atguigu.rabbitmq.simple.Consumer</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.simple;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.util.concurrent.TimeoutException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br> <br>        <span class="hljs-comment">//1.创建连接工厂</span><br>        ConnectionFactory factory = <span class="hljs-keyword">new</span> ConnectionFactory();<br>        <span class="hljs-comment">//2. 设置参数</span><br>        factory.setHost(<span class="hljs-string">&quot;192.168.137.118&quot;</span>);<span class="hljs-comment">//ip</span><br>        factory.setPort(<span class="hljs-number">5672</span>); <span class="hljs-comment">//端口  默认值 5672</span><br>        factory.setVirtualHost(<span class="hljs-string">&quot;/&quot;</span>);<span class="hljs-comment">//虚拟机 默认值/</span><br>        factory.setUsername(<span class="hljs-string">&quot;admin&quot;</span>);<span class="hljs-comment">//用户名</span><br>        factory.setPassword(<span class="hljs-string">&quot;123456&quot;</span>);<span class="hljs-comment">//密码</span><br>        <span class="hljs-comment">//3. 创建连接 Connection</span><br>        Connection connection = factory.newConnection();<br>        <span class="hljs-comment">//4. 创建Channel</span><br>        Channel channel = connection.createChannel();<br>        <span class="hljs-comment">//5. 创建队列Queue</span><br>        <span class="hljs-comment">/*</span><br><span class="hljs-comment">        queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map&lt;String, Object&gt; arguments)</span><br><span class="hljs-comment">        参数：</span><br><span class="hljs-comment">            1. queue：队列名称</span><br><span class="hljs-comment">            2. durable：是否持久化,当mq重启之后,还在</span><br><span class="hljs-comment">            3. exclusive：</span><br><span class="hljs-comment">                * 是否独占。只能有一个消费者监听这队列</span><br><span class="hljs-comment">                * 当Connection关闭时,是否删除队列</span><br><span class="hljs-comment">            4. autoDelete：是否自动删除。当没有Consumer时,自动删除掉</span><br><span class="hljs-comment">            5. arguments：参数。</span><br><span class="hljs-comment">         */</span><br>        <span class="hljs-comment">//如果没有一个名字叫simple_queue的队列,则会创建该队列,如果有则不会创建</span><br>        channel.queueDeclare(<span class="hljs-string">&quot;simple_queue&quot;</span>,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br> <br>        <span class="hljs-comment">// 接收消息</span><br>        DefaultConsumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-comment">/*</span><br><span class="hljs-comment">               回调方法,当收到消息后,会自动执行该方法</span><br><span class="hljs-comment">               1. consumerTag：标识</span><br><span class="hljs-comment">               2. envelope：获取一些信息,交换机,路由key...</span><br><span class="hljs-comment">               3. properties：配置信息</span><br><span class="hljs-comment">               4. body：数据</span><br><span class="hljs-comment">            */</span><br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;consumerTag：&quot;</span>+consumerTag);<br>                System.out.println(<span class="hljs-string">&quot;Exchange：&quot;</span>+envelope.getExchange());<br>                System.out.println(<span class="hljs-string">&quot;RoutingKey：&quot;</span>+envelope.getRoutingKey());<br>                System.out.println(<span class="hljs-string">&quot;properties：&quot;</span>+properties);<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>            &#125;<br>        &#125;;<br>        <span class="hljs-comment">/*</span><br><span class="hljs-comment">        basicConsume(String queue, boolean autoAck, Consumer callback)</span><br><span class="hljs-comment">        参数：</span><br><span class="hljs-comment">            1. queue：队列名称</span><br><span class="hljs-comment">            2. autoAck：是否自动确认 ,类似咱们发短信,发送成功会收到一个确认消息</span><br><span class="hljs-comment">            3. callback：回调对象</span><br><span class="hljs-comment">         */</span><br>        <span class="hljs-comment">// 消费者类似一个监听程序,主要是用来监听消息</span><br>        channel.basicConsume(<span class="hljs-string">&quot;simple_queue&quot;</span>,<span class="hljs-keyword">true</span>,consumer);<br>   &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行程序</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image048.gif?versionId=CAEQKRiBgMCIiayA.hciIGEwMjZkNzYwNDg0NTQzZTM4YmVmYWQwYzIyNDAzYzIx" srcset="/img/loading.gif" lazyload alt="img"></p>
<h2 id="3-4-小结"><a href="#3-4-小结" class="headerlink" title="3.4. 小结"></a>3.4. 小结</h2><p>上述的入门案例中中其实使用的是如下的简单模式：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image048.gif?versionId=CAEQKRiBgMCIiayA.hciIGEwMjZkNzYwNDg0NTQzZTM4YmVmYWQwYzIyNDAzYzIx" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>在上图的模型中，有以下概念：</p>
<ul>
<li>P：生产者，也就是要发送消息的程序</li>
<li>C：消费者：消息的接受者，会一直等待消息到来。</li>
<li>queue：消息队列，图中红色部分。类似一个邮箱，可以缓存消息；生产者向其中投递消息，消费者从其中取出消息。</li>
</ul>
<h1 id="4-AMQP"><a href="#4-AMQP" class="headerlink" title="4. AMQP"></a>4. AMQP</h1><h2 id="4-1-相关概念介绍"><a href="#4-1-相关概念介绍" class="headerlink" title="4.1. 相关概念介绍"></a>4.1. 相关概念介绍</h2><p>AMQP 一个提供统一消息服务的应用层标准高级消息队列协议，是应用层协议的一个开放标准，为面向消息的中间件设计。</p>
<p>RabbitMQ是AMQP协议的Erlang的实现。</p>
<table>
<thead>
<tr>
<th><strong>概念</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>连接Connection</td>
<td>一个网络连接，比如TCP/IP套接字连接。</td>
</tr>
<tr>
<td>信道Channel</td>
<td>多路复用连接中的一条独立的双向数据流通道。为会话提供物理传输介质。</td>
</tr>
<tr>
<td>客户端Client</td>
<td>AMQP连接或者会话的发起者。AMQP是非对称的，客户端生产和消费消息，服务器存储和路由这些消息。</td>
</tr>
<tr>
<td>服务节点Broker</td>
<td>消息中间件的服务节点；一般情况下可以将一个RabbitMQ  Broker看作一台RabbitMQ 服务器。</td>
</tr>
<tr>
<td>端点</td>
<td>AMQP对话的任意一方。一个AMQP连接包括两个端点（一个是客户端，一个是服务器）。</td>
</tr>
<tr>
<td>消费者Consumer</td>
<td>一个从消息队列里请求消息的客户端程序。</td>
</tr>
<tr>
<td>生产者Producer</td>
<td>一个向交换机发布消息的客户端应用程序。</td>
</tr>
</tbody></table>
<h2 id="4-2-RabbitMQ运转流程"><a href="#4-2-RabbitMQ运转流程" class="headerlink" title="4.2. RabbitMQ运转流程"></a>4.2. RabbitMQ运转流程</h2><p>在入门案例中：</p>
<ul>
<li>生产者发送消息</li>
</ul>
<ol>
<li>生产者创建连接（Connection），开启一个信道（Channel），连接到RabbitMQ Broker；</li>
<li>声明队列并设置属性；如是否排它，是否持久化，是否自动删除；</li>
<li>将路由键（空字符串）与队列绑定起来；</li>
<li>发送消息至RabbitMQ Broker；</li>
<li>关闭信道；</li>
<li>关闭连接；</li>
</ol>
<ul>
<li>消费者接收消息</li>
</ul>
<ol>
<li>消费者创建连接（Connection），开启一个信道（Channel），连接到RabbitMQ Broker</li>
<li>向Broker 请求消费相应队列中的消息，设置相应的回调函数；</li>
<li>等待Broker投递响应队列中的消息，消费者接收消息；</li>
<li>确认（ack，自动确认）接收到的消息；</li>
<li>RabbitMQ从队列中删除相应已经被确认的消息；</li>
<li>关闭信道；</li>
<li>关闭连接；</li>
</ol>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image052.gif?versionId=CAEQKRiCgMCMiayA.hciIGUyYWU3NGExNDQyZDQ3NWFiNThhNTQ4NDNkZDlmNGMx" srcset="/img/loading.gif" lazyload alt="img"></p>
<h1 id="5-RabbitMQ工作模式"><a href="#5-RabbitMQ工作模式" class="headerlink" title="5. RabbitMQ工作模式"></a>5. RabbitMQ工作模式</h1><h2 id="5-1-Work-queues工作队列模式"><a href="#5-1-Work-queues工作队列模式" class="headerlink" title="5.1. Work queues工作队列模式"></a>5.1. Work queues工作队列模式</h2><h3 id="5-1-1-模式说明"><a href="#5-1-1-模式说明" class="headerlink" title="5.1.1. 模式说明"></a>5.1.1. 模式说明</h3><p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image054.gif?versionId=CAEQKRiBgMCBiayA.hciIDAyYmE2MWM4ZjliZTQ4ZGI4NWI4ZTgxMGU1MzBlM2Ix" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><code>Work Queues</code>与入门程序的<code>简单模式</code>相比，多了一个或一些消费端，多个消费端共同消费同一个队列中的消息。</p>
<p><strong>应用场景</strong>：对于 任务过重或任务较多情况使用工作队列可以<strong>提高<strong><strong>任务处理的</strong></strong>速度</strong>。</p>
<h3 id="5-1-2-代码"><a href="#5-1-2-代码" class="headerlink" title="5.1.2. 代码"></a>5.1.2. 代码</h3><p><code>Work Queues</code>与入门程序的<code>简单模式</code>的代码是几乎一样的；可以完全复制，并复制多一个消费者进行多个消费者同时消费消息的测试。</p>
<h4 id="1）抽取工具类"><a href="#1）抽取工具类" class="headerlink" title="1）抽取工具类"></a>1）抽取工具类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConnectionUtil</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Connection <span class="hljs-title">getConnection</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        <span class="hljs-comment">//定义连接工厂</span><br>        ConnectionFactory factory = <span class="hljs-keyword">new</span> ConnectionFactory();<br>        <span class="hljs-comment">//设置服务地址</span><br>        factory.setHost(<span class="hljs-string">&quot;192.168.137.118&quot;</span>);<br>        <span class="hljs-comment">//端口</span><br>        factory.setPort(<span class="hljs-number">5672</span>);<br>        <span class="hljs-comment">//设置账号信息，用户名、密码、vhost</span><br>        factory.setVirtualHost(<span class="hljs-string">&quot;/&quot;</span>);<br>        factory.setUsername(<span class="hljs-string">&quot;admin&quot;</span>);<br>        factory.setPassword(<span class="hljs-string">&quot;123456&quot;</span>);<br>        <span class="hljs-comment">// 通过工程获取连接</span><br>        Connection connection = factory.newConnection();<br>        <span class="hljs-keyword">return</span> connection;<br>    &#125;<br> <br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection con = ConnectionUtil.getConnection();<br>        System.out.println(con);<br>        <span class="hljs-comment">//         amqp://admin@192.168.137.118:5672/</span><br>        con.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="2）生产者"><a href="#2）生产者" class="headerlink" title="2）生产者"></a>2）生产者</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Producer</span> </span>&#123;<br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String QUEUE_NAME = <span class="hljs-string">&quot;work_queue&quot;</span>;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        channel.queueDeclare(QUEUE_NAME,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">10</span>; i++) &#123;<br>            String body = i+<span class="hljs-string">&quot;hello rabbitmq~~~&quot;</span>;<br>            channel.basicPublish(<span class="hljs-string">&quot;&quot;</span>,QUEUE_NAME,<span class="hljs-keyword">null</span>,body.getBytes());<br>        &#125;<br>        channel.close();<br>        connection.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image056.gif?versionId=CAEQKRiBgMCCiayA.hciIDA5ODUzZDc4N2VhOTQ4MTBiMWFlNGUyMjFhODczZTli" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="3）消费者1"><a href="#3）消费者1" class="headerlink" title="3）消费者1"></a>3）消费者1</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.work;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer1</span> </span>&#123;<br>    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String QUEUE_NAME = <span class="hljs-string">&quot;work_queue&quot;</span>;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        channel.queueDeclare(QUEUE_NAME,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(QUEUE_NAME,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="4）消费者2"><a href="#4）消费者2" class="headerlink" title="4）消费者2"></a>4）消费者2</h4><p><strong>Consumer2</strong>与<strong>Consumer1****类一样。省略。</strong></p>
<p>运行两个消费者</p>
<h3 id="5-1-3-测试"><a href="#5-1-3-测试" class="headerlink" title="5.1.3. 测试"></a>5.1.3. 测试</h3><p>启动两个消费者，然后再启动生产者发送消息；到IDEA的两个消费者对应的控制台查看是否竞争性的接收到消息。</p>
<h3 id="5-1-4-小结"><a href="#5-1-4-小结" class="headerlink" title="5.1.4. 小结"></a>5.1.4. 小结</h3><ol>
<li>在一个队列中如果有多个消费者，那么消费者之间对于同一个消息的关系是<strong>竞争</strong>的关系。</li>
<li><strong>Work Queues</strong> 对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。</li>
</ol>
<h2 id="5-2-订阅模式类型"><a href="#5-2-订阅模式类型" class="headerlink" title="5.2. 订阅模式类型"></a>5.2. 订阅模式类型</h2><p>订阅模式示例图：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image058.gif?versionId=CAEQKRiBgMDQiKyA.hciIDRlZWQ5MDExMDQ5MDRiMjdhYjRhMGNhYjA0OWZjN2Y4" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>前面2个案例中，只有3个角色：</p>
<ul>
<li>P：生产者，也就是要发送消息的程序</li>
<li>C：消费者：消息的接受者，会一直等待消息到来。</li>
<li>queue：消息队列，图中红色部分</li>
</ul>
<p>而在订阅模型中，多了一个exchange角色，而且过程略有变化：</p>
<ul>
<li><p>P：生产者，也就是要发送消息的程序，但是不再发送到队列中，而是发给X（交换机）</p>
</li>
<li><p>C：消费者，消息的接受者，会一直等待消息到来。</p>
</li>
<li><p>Queue：消息队列，接收消息、缓存消息。</p>
</li>
<li><p>Exchange：交换机，图中的X。一方面，接收生产者发送的消息。另一方面，知道如何处理消息，例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作，取决于Exchange的类型。<strong>Exchange<strong><strong>有常见以下</strong></strong>3****种类型</strong>：</p>
</li>
<li><ul>
<li>Fanout：广播，将消息交给所有绑定到交换机的队列</li>
<li>Direct：定向，把消息交给符合指定routing key 的队列</li>
<li>Topic：通配符，把消息交给符合routing pattern（路由模式） 的队列</li>
</ul>
</li>
</ul>
<p><strong>Exchange****（交换机）只负责转发消息，不具备存储消息的能力</strong>，因此如果没有任何队列与Exchange绑定，或者没有符合路由规则的队列，那么消息会丢失！</p>
<h2 id="5-3-Publish-Subscribe发布与订阅模式"><a href="#5-3-Publish-Subscribe发布与订阅模式" class="headerlink" title="5.3. Publish/Subscribe发布与订阅模式"></a>5.3. Publish/Subscribe发布与订阅模式</h2><h3 id="5-3-1-模式说明"><a href="#5-3-1-模式说明" class="headerlink" title="5.3.1. 模式说明"></a>5.3.1. 模式说明</h3><p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image060.gif?versionId=CAEQKRiBgICZh6yA.hciIGE5MTEwMDU3YjlmNjQxZTY5Yjc0NTAxOGZiMmY0ZTc5" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>发布订阅模式：<br> 1、每个消费者监听自己的队列。<br> 2、生产者将消息发给broker，由交换机将消息转发到绑定此交换机的每个队列，每个绑定交换机的队列都将接收<br> 到消息</p>
<h3 id="5-3-2-代码"><a href="#5-3-2-代码" class="headerlink" title="5.3.2. 代码"></a>5.3.2. 代码</h3><h4 id="1）生产者"><a href="#1）生产者" class="headerlink" title="1）生产者"></a>1）生产者</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.fanout;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.BuiltinExchangeType;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Channel;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Connection;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.ConnectionFactory;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Producer</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br> <br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        <span class="hljs-comment">/*</span><br><span class="hljs-comment">       exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map&lt;String, Object&gt; arguments)</span><br><span class="hljs-comment">       参数：</span><br><span class="hljs-comment">        1. exchange：交换机名称</span><br><span class="hljs-comment">        2. type：交换机类型</span><br><span class="hljs-comment">            DIRECT(&quot;direct&quot;),：定向</span><br><span class="hljs-comment">            FANOUT(&quot;fanout&quot;),：扇形（广播）,发送消息到每一个与之绑定队列。</span><br><span class="hljs-comment">            TOPIC(&quot;topic&quot;),通配符的方式</span><br><span class="hljs-comment">            HEADERS(&quot;headers&quot;);参数匹配</span><br><span class="hljs-comment">        3. durable：是否持久化</span><br><span class="hljs-comment">        4. autoDelete：自动删除</span><br><span class="hljs-comment">        5. internal：内部使用。 一般false</span><br><span class="hljs-comment">        6. arguments：参数</span><br><span class="hljs-comment">        */</span><br>        String exchangeName = <span class="hljs-string">&quot;test_fanout&quot;</span>;<br>        <span class="hljs-comment">//5. 创建交换机</span><br>        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        <span class="hljs-comment">//6. 创建队列</span><br>        String queue1Name = <span class="hljs-string">&quot;test_fanout_queue1&quot;</span>;<br>        String queue2Name = <span class="hljs-string">&quot;test_fanout_queue2&quot;</span>;<br>        channel.queueDeclare(queue1Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        channel.queueDeclare(queue2Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        <span class="hljs-comment">//7. 绑定队列和交换机</span><br>        <span class="hljs-comment">/*</span><br><span class="hljs-comment">        queueBind(String queue, String exchange, String routingKey)</span><br><span class="hljs-comment">        参数：</span><br><span class="hljs-comment">            1. queue：队列名称</span><br><span class="hljs-comment">            2. exchange：交换机名称</span><br><span class="hljs-comment">            3. routingKey：路由键,绑定规则</span><br><span class="hljs-comment">                如果交换机的类型为fanout ,routingKey设置为&quot;&quot;</span><br><span class="hljs-comment">         */</span><br>        channel.queueBind(queue1Name,exchangeName,<span class="hljs-string">&quot;&quot;</span>);<br>        channel.queueBind(queue2Name,exchangeName,<span class="hljs-string">&quot;&quot;</span>);<br> <br>        String body = <span class="hljs-string">&quot;日志信息：张三调用了findAll方法...日志级别：info...&quot;</span>;<br>        <span class="hljs-comment">//8. 发送消息</span><br>        channel.basicPublish(exchangeName,<span class="hljs-string">&quot;&quot;</span>,<span class="hljs-keyword">null</span>,body.getBytes());<br> <br>        <span class="hljs-comment">//9. 释放资源</span><br>        channel.close();<br>        connection.close();<br>    &#125;<br>&#125;    <br></code></pre></td></tr></table></figure>

<p>运行</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image062.gif?versionId=CAEQKRiBgMCXh6yA.hciIGRmMjVlZjI2Y2NhNDQwZDNiZTUwNWEzMjNiMjkzNDBm" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="2）消费者1"><a href="#2）消费者1" class="headerlink" title="2）消费者1"></a>2）消费者1</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.fanout;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer1</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue1Name = <span class="hljs-string">&quot;test_fanout_queue1&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>                System.out.println(<span class="hljs-string">&quot;将日志信息打印到控制台.....&quot;</span>);<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue1Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="3）消费者2"><a href="#3）消费者2" class="headerlink" title="3）消费者2"></a>3）消费者2</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.fanout;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer2</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue2Name = <span class="hljs-string">&quot;test_fanout_queue2&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>                System.out.println(<span class="hljs-string">&quot;将日志信息打印到控制台.....&quot;</span>);<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue2Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="5-3-3-测试"><a href="#5-3-3-测试" class="headerlink" title="5.3.3. 测试"></a>5.3.3. 测试</h3><p>启动所有消费者，然后使用生产者发送消息；在每个消费者对应的控制台可以查看到生产者发送的所有消息；到达<strong>广播</strong>的效果。</p>
<p>在执行完测试代码后，其实到RabbitMQ的管理后台找到<code>Exchanges</code>选项卡，点击 <code>fanout_exchange</code> 的交换机，可以查看到如下的绑定：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image064.jpg?versionId=CAEQKRiBgICKh6yA.hciIDFkMjg4NmMyOGQyMDQ5ZWVhZjdjYTU3MjU3MjMzNjhl" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="5-3-4-小结"><a href="#5-3-4-小结" class="headerlink" title="5.3.4. 小结"></a>5.3.4. 小结</h3><p>交换机需要与队列进行绑定，绑定之后；一个消息可以被多个消费者都收到。</p>
<p><strong>发布订阅模式与工作队列模式的区别</strong></p>
<p>1、工作队列模式不用定义交换机，而发布/订阅模式需要定义交换机。</p>
<p>2、发布/订阅模式的生产方是面向交换机发送消息，工作队列模式的生产方是面向队列发送消息(底层使用默认交换机)。</p>
<p>3、发布/订阅模式需要设置队列和交换机的绑定，工作队列模式不需要设置，实际上工作队列模式会将队列绑 定到默认的交换机 。</p>
<h2 id="5-4-Routing路由模式"><a href="#5-4-Routing路由模式" class="headerlink" title="5.4. Routing路由模式"></a>5.4. Routing路由模式</h2><h3 id="5-4-1-模式说明"><a href="#5-4-1-模式说明" class="headerlink" title="5.4.1. 模式说明"></a>5.4.1. 模式说明</h3><p>路由模式特点：</p>
<ul>
<li>队列与交换机的绑定，不能是任意绑定了，而是要指定一个<code>RoutingKey</code>（路由key）</li>
<li>消息的发送方在 向 Exchange发送消息时，也必须指定消息的 <code>RoutingKey</code>。</li>
<li>Exchange不再把消息交给每一个绑定的队列，而是根据消息的<code>Routing Key</code>进行判断，只有队列的<code>Routingkey</code>与消息的 <code>Routing key</code>完全一致，才会接收到消息</li>
</ul>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image066.gif?versionId=CAEQKRiBgICBh6yA.hciIGJiZjEzYTNkMjNjMzRjN2U4MzBlOWJlNGU5MzE3ZmU2" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>图解：</p>
<ul>
<li>P：生产者，向Exchange发送消息，发送消息时，会指定一个routing key。</li>
<li>X：Exchange（交换机），接收生产者的消息，然后把消息递交给 与routing key完全匹配的队列</li>
<li>C1：消费者，其所在队列指定了需要routing key 为 error 的消息</li>
<li>C2：消费者，其所在队列指定了需要routing key 为 info、error、warning 的消息</li>
</ul>
<h3 id="5-4-2-代码"><a href="#5-4-2-代码" class="headerlink" title="5.4.2. 代码"></a>5.4.2. 代码</h3><p>在编码上与 <code>Publish/Subscribe``发布与订阅模式</code> 的区别是交换机的类型为：Direct，还有队列绑定交换机的时候需要指定routing key。</p>
<h4 id="1）生产者-1"><a href="#1）生产者-1" class="headerlink" title="1）生产者"></a>1）生产者</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.routing;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.BuiltinExchangeType;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Channel;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Connection;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.ConnectionFactory;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Producer</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>       Connection connection = ConnectionUtil.getConnection();<br>       Channel channel = connection.createChannel();<br>       String exchangeName = <span class="hljs-string">&quot;test_direct&quot;</span>;<br>       <span class="hljs-comment">// 创建交换机</span><br>       channel.exchangeDeclare(exchangeName,BuiltinExchangeType.DIRECT,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>       <span class="hljs-comment">// 创建队列</span><br>       String queue1Name = <span class="hljs-string">&quot;test_direct_queue1&quot;</span>;<br>       String queue2Name = <span class="hljs-string">&quot;test_direct_queue2&quot;</span>;<br>        <span class="hljs-comment">// 声明（创建）队列</span><br>       channel.queueDeclare(queue1Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>       channel.queueDeclare(queue2Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>       <span class="hljs-comment">// 队列绑定交换机</span><br>        <span class="hljs-comment">// 队列1绑定error</span><br>        channel.queueBind(queue1Name,exchangeName,<span class="hljs-string">&quot;error&quot;</span>);<br>        <span class="hljs-comment">// 队列2绑定info error warning</span><br>        channel.queueBind(queue2Name,exchangeName,<span class="hljs-string">&quot;info&quot;</span>);<br>        channel.queueBind(queue2Name,exchangeName,<span class="hljs-string">&quot;error&quot;</span>);<br>        channel.queueBind(queue2Name,exchangeName,<span class="hljs-string">&quot;warning&quot;</span>);<br> <br>        String message = <span class="hljs-string">&quot;日志信息：张三调用了delete方法.错误了,日志级别warning&quot;</span>;<br>        <span class="hljs-comment">// 发送消息</span><br>        channel.basicPublish(exchangeName,<span class="hljs-string">&quot;warning&quot;</span>,<span class="hljs-keyword">null</span>,message.getBytes());<br>        System.out.println(message);<br> <br>        channel.close();<br>        connection.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image068.gif?versionId=CAEQKRiBgID1hqyA.hciIDQwNTUzMjRmZmYxYTRlZGU4NTM5ODJkMTg4NWZjZTAw" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image070.gif?versionId=CAEQKRiBgID6hqyA.hciIDU2Y2JiNjRjOTMxNTQyOTk5NzY3Njg0YmJiMTdmZjNh" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="2）消费者1-1"><a href="#2）消费者1-1" class="headerlink" title="2）消费者1"></a>2）消费者1</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.routing;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer1</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue1Name = <span class="hljs-string">&quot;test_direct_queue1&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>                System.out.println(<span class="hljs-string">&quot;将日志信息打印到控制台.....&quot;</span>);<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue1Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="3）消费者2-1"><a href="#3）消费者2-1" class="headerlink" title="3）消费者2"></a>3）消费者2</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.routing;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer2</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue2Name = <span class="hljs-string">&quot;test_direct_queue2&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>                System.out.println(<span class="hljs-string">&quot;将日志信息存储到数据库.....&quot;</span>);<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue2Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="5-4-3-测试"><a href="#5-4-3-测试" class="headerlink" title="5.4.3. 测试"></a>5.4.3. 测试</h3><p>启动所有消费者，然后使用生产者发送消息；在消费者对应的控制台可以查看到生产者发送对应routing key对应队列的消息；到达<strong>按照需要接收</strong>的效果。</p>
<h3 id="5-4-4-小结"><a href="#5-4-4-小结" class="headerlink" title="5.4.4. 小结"></a>5.4.4. 小结</h3><p>Routing模式要求队列在绑定交换机时要指定routing key，消息会转发到符合routing key的队列。</p>
<h2 id="5-5-Topics通配符模式"><a href="#5-5-Topics通配符模式" class="headerlink" title="5.5. Topics通配符模式"></a>5.5. Topics通配符模式</h2><h3 id="5-5-1-模式说明"><a href="#5-5-1-模式说明" class="headerlink" title="5.5.1. 模式说明"></a>5.5.1. 模式说明</h3><p><code>Topic</code>类型与<code>Direct</code>相比，都是可以根据<code>RoutingKey</code>把消息路由到不同的队列。只不过<code>Topic</code>类型<code>Exchange</code>可以让队列在绑定<code>Routing key</code> 的时候<strong>使用通配符</strong>！</p>
<figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs xquery">Routingkey 一般都是有一个或多个单词组成，多个单词之间以”.”分割，例如： <span class="hljs-type">item</span>.<span class="hljs-keyword">insert</span><br></code></pre></td></tr></table></figure>

<p>通配符规则：</p>
<p><code>#</code>：匹配零个或多个词</p>
<p><code>*</code>：匹配不多不少恰好1个词</p>
<p>举例：</p>
<figure class="highlight autohotkey"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs autohotkey">item.#`：能够匹配`item.insert.abc` 或者 `item.insert<br>item.*`：只能匹配`item.insert<br></code></pre></td></tr></table></figure>

<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image072.gif?versionId=CAEQKRiBgIDthqyA.hciIDQ5NGYwZmNlNGM3ODQ4MjM5ZWQwZWQxNmEyMTQ0MjA2" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image074.gif?versionId=CAEQKRiBgID0hqyA.hciIDgwMDE3ZGVkODBmNjQwNmVhODNmMDQ0MWJmYWJlZmI4" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>图解：</p>
<ul>
<li>红色Queue：绑定的是<code>usa.#</code> ，因此凡是以 <code>usa.</code>开头的<code>routing     key</code> 都会被匹配到</li>
<li>黄色Queue：绑定的是<code>#.news</code> ，因此凡是以 <code>.news</code>结尾的 <code>routing key</code> 都会被匹配</li>
</ul>
<h3 id="5-5-2-代码"><a href="#5-5-2-代码" class="headerlink" title="5.5.2. 代码"></a>5.5.2. 代码</h3><h4 id="1）生产者-2"><a href="#1）生产者-2" class="headerlink" title="1）生产者"></a>1）生产者</h4><p>使用topic类型的Exchange，发送消息的routing key有3种： <code>order.info</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.topic;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.BuiltinExchangeType;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Channel;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.Connection;<br><span class="hljs-keyword">import</span> com.rabbitmq.client.ConnectionFactory;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Producer</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String exchangeName = <span class="hljs-string">&quot;test_topic&quot;</span>;<br>        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        String queue1Name = <span class="hljs-string">&quot;test_topic_queue1&quot;</span>;<br>        String queue2Name = <span class="hljs-string">&quot;test_topic_queue2&quot;</span>;<br>        channel.queueDeclare(queue1Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        channel.queueDeclare(queue2Name,<span class="hljs-keyword">true</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">false</span>,<span class="hljs-keyword">null</span>);<br>        <span class="hljs-comment">// 绑定队列和交换机</span><br>        <span class="hljs-comment">/**</span><br><span class="hljs-comment">         *  参数：</span><br><span class="hljs-comment">             1. queue：队列名称</span><br><span class="hljs-comment">             2. exchange：交换机名称</span><br><span class="hljs-comment">             3. routingKey：路由键,绑定规则</span><br><span class="hljs-comment">                 如果交换机的类型为fanout ,routingKey设置为&quot;&quot;</span><br><span class="hljs-comment">         */</span><br>        <span class="hljs-comment">// routing key  系统的名称.日志的级别。</span><br>        <span class="hljs-comment">//需求： 所有error级别的日志存入数据库,所有order系统的日志存入数据库</span><br>        channel.queueBind(queue1Name,exchangeName,<span class="hljs-string">&quot;#.error&quot;</span>);<br>        channel.queueBind(queue1Name,exchangeName,<span class="hljs-string">&quot;order.*&quot;</span>);<br>        channel.queueBind(queue2Name,exchangeName,<span class="hljs-string">&quot;*.*&quot;</span>);<br>        String body = <span class="hljs-string">&quot;日志信息：张三调用了findAll方法...日志级别：info...&quot;</span>;<br>        <span class="hljs-comment">//发送消息goods.info,goods.error</span><br>        channel.basicPublish(exchangeName,<span class="hljs-string">&quot;order.info&quot;</span>,<span class="hljs-keyword">null</span>,body.getBytes());<br>        channel.close();<br>        connection.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行程序</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image076.gif?versionId=CAEQKRiBgMDthqyA.hciIDY1MmZmZmE5ZjFmZDQzNTA5Mjg2ODUxM2RhZWJlNDE3" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image078.gif?versionId=CAEQKRiBgMDkhqyA.hciIDhmMTBjYWYxOGM5NzQ4MGJiM2RiZWQzOGE5OTBmYzM0" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="2）消费者1-2"><a href="#2）消费者1-2" class="headerlink" title="2）消费者1"></a>2）消费者1</h4><p>接收两种类型的消息：更新商品和删除商品</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.topic;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer1</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue1Name = <span class="hljs-string">&quot;test_topic_queue1&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue1Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="3）消费者2-2"><a href="#3）消费者2-2" class="headerlink" title="3）消费者2"></a>3）消费者2</h4><p>接收所有类型的消息：新增商品,更新商品和删除商品。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.topic;<br> <br><span class="hljs-keyword">import</span> com.rabbitmq.client.*;<br><span class="hljs-keyword">import</span> java.io.IOException;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Consumer2</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        Connection connection = ConnectionUtil.getConnection();<br>        Channel channel = connection.createChannel();<br>        String queue2Name = <span class="hljs-string">&quot;test_topic_queue2&quot;</span>;<br>        Consumer consumer = <span class="hljs-keyword">new</span> DefaultConsumer(channel)&#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleDelivery</span><span class="hljs-params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="hljs-keyword">byte</span>[] body)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>                System.out.println(<span class="hljs-string">&quot;body：&quot;</span>+<span class="hljs-keyword">new</span> String(body));<br>            &#125;<br>        &#125;;<br>        channel.basicConsume(queue2Name,<span class="hljs-keyword">true</span>,consumer);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="5-5-3-测试"><a href="#5-5-3-测试" class="headerlink" title="5.5.3. 测试"></a>5.5.3. 测试</h3><p>启动所有消费者，然后使用生产者发送消息；在消费者对应的控制台可以查看到生产者发送对应routing key对应队列的消息；到达<strong>按照需要接收</strong>的效果；并且这些routing key可以使用通配符。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image080.gif?versionId=CAEQKRiBgMDrhKyA.hciIDFmNzU5MzY5NDRjZTQ5MzhhNjAyODllZjczM2YyZDQ0" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="5-5-4-小结"><a href="#5-5-4-小结" class="headerlink" title="5.5.4. 小结"></a>5.5.4. 小结</h3><p>Topic主题模式可以实现 <code>Publish/Subscribe``发布与订阅模式</code> 和 <code>Routing``路由模式</code> 的功能；只是Topic在配置routing key 的时候可以使用通配符，显得更加灵活。</p>
<h2 id="5-6-模式总结"><a href="#5-6-模式总结" class="headerlink" title="5.6. 模式总结"></a>5.6. 模式总结</h2><p>RabbitMQ工作模式：<br> <strong>1、简单模式 HelloWorld</strong><br> 一个生产者、一个消费者，不需要设置交换机（使用默认的交换机）</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image082.jpg?versionId=CAEQKRiCgMDShKyA.hciIDU4MDljNTQ3MDMyNjQ1ZmNiYTJmODRmZDAzMWU4OGI2" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>2</strong>、工作队列模式 <strong>Work Queue</strong><br> 一个生产者、多个消费者（竞争关系），不需要设置交换机（使用默认的交换机）</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image084.jpg?versionId=CAEQKRiBgMDWhKyA.hciIDYxYTFlZWIxZDU4YzQ1ZjU4M2UzZGM2NDhiMjc0ODBl" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>3、发布订阅模式 Publish/subscribe</strong><br> 需要设置类型为fanout的交换机，并且交换机和队列进行绑定，当发送消息到交换机后，交换机会将消息发送到绑定的队列</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image086.jpg?versionId=CAEQKRiBgMDjhKyA.hciIGIxNzg5OWM4Mjk2OTQxMGI4NjdkOTZlYmE2YzRmZTM3" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>4、路由模式</strong> <strong>Routing</strong><br> 需要设置类型为direct的交换机，交换机和队列进行绑定，并且指定routing key，当发送消息到交换机后，交换机会根据routing key将消息发送到对应的队列</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image088.jpg?versionId=CAEQKRiBgMDOhKyA.hciIGI5ZjY3ZmZkNWJkNTQwZjU5NmVmZWQxOTU1ZjZlYmNm" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>5、通配符模式</strong> <strong>Topic</strong><br> 需要设置类型为topic的交换机，交换机和队列进行绑定，并且指定通配符方式的routing key，当发送消息到交换机后，交换机会根据routing key将消息发送到对应的队列</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image090.jpg?versionId=CAEQKRiBgIDShKyA.hciIGI0ODgwZTU0ZWJlODRmMGM5NDQxOWY2ODVlYzA3YzZj" srcset="/img/loading.gif" lazyload alt="img"></p>
<h1 id="6-Spring-整合RabbitMQ"><a href="#6-Spring-整合RabbitMQ" class="headerlink" title="6 Spring 整合RabbitMQ"></a>6 Spring 整合RabbitMQ</h1><h2 id="6-1-搭建生产者工程"><a href="#6-1-搭建生产者工程" class="headerlink" title="6.1. 搭建生产者工程"></a>6.1. 搭建生产者工程</h2><h3 id="6-1-1-创建工程spring-rabbitmq-producer"><a href="#6-1-1-创建工程spring-rabbitmq-producer" class="headerlink" title="6.1.1. 创建工程spring-rabbitmq-producer"></a>6.1.1. 创建工程spring-rabbitmq-producer</h3><h3 id="6-1-2-添加依赖"><a href="#6-1-2-添加依赖" class="headerlink" title="6.1.2. 添加依赖"></a>6.1.2. 添加依赖</h3><p>修改pom.xml文件内容为如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.atguigu<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-rabbitmq-producer<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-context<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.7.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.amqp<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-rabbit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.1.8.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.12<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.7.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br>    <br>     <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.8.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br> <br><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="6-1-3-配置整合"><a href="#6-1-3-配置整合" class="headerlink" title="6.1.3. 配置整合"></a>6.1.3. 配置整合</h3><p>1 创建<code>rabbitmq.properties</code>连接参数等配置文件；</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">rabbitmq.host</span>=<span class="hljs-string">192.168.137.118</span><br><span class="hljs-meta">rabbitmq.port</span>=<span class="hljs-string">5672</span><br><span class="hljs-meta">rabbitmq.username</span>=<span class="hljs-string">admin</span><br><span class="hljs-meta">rabbitmq.password</span>=<span class="hljs-string">123456</span><br><span class="hljs-meta">rabbitmq.virtual-host</span>=<span class="hljs-string">/</span><br></code></pre></td></tr></table></figure>



<p>2 创建 <code>spring-rabbitmq.xml</code> 整合配置文件；</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">beans</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/beans&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:context</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/context&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:rabbit</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/rabbit&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/beans</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/context</span></span><br><span class="hljs-string"><span class="hljs-tag">       https://www.springframework.org/schema/context/spring-context.xsd</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/rabbit</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--加载配置文件--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">context:property-placeholder</span> <span class="hljs-attr">location</span>=<span class="hljs-string">&quot;classpath:rabbitmq.properties&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!-- 定义rabbitmq connectionFactory --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:connection-factory</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;connectionFactory&quot;</span> <span class="hljs-attr">host</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.host&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">port</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.port&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">username</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.username&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">password</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.password&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">virtual-host</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.virtual-host&#125;&quot;</span>/&gt;</span><br>    <span class="hljs-comment">&lt;!--定义管理交换机、队列--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:admin</span> <span class="hljs-attr">connection-factory</span>=<span class="hljs-string">&quot;connectionFactory&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!--定义持久化队列,不存在则自动创建；不绑定到交换机则绑定到默认交换机</span><br><span class="hljs-comment">    默认交换机类型为direct,名字为：&quot;&quot;,路由键为队列的名称</span><br><span class="hljs-comment">    --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_queue&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_queue&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~广播；所有队列都能收到消息~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;</span><br>    <span class="hljs-comment">&lt;!--定义广播交换机中的持久化队列,不存在则自动创建--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_fanout_queue_1&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_fanout_queue_1&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!--定义广播交换机中的持久化队列,不存在则自动创建--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_fanout_queue_2&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_fanout_queue_2&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!--定义广播类型交换机；并绑定上述两个队列--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:fanout-exchange</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_fanout_exchange&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_fanout_exchange&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:bindings</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:binding</span> <span class="hljs-attr">queue</span>=<span class="hljs-string">&quot;spring_fanout_queue_1&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:binding</span> <span class="hljs-attr">queue</span>=<span class="hljs-string">&quot;spring_fanout_queue_2&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">rabbit:bindings</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">rabbit:fanout-exchange</span>&gt;</span><br> <br>    <span class="hljs-comment">&lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~通配符；*匹配一个单词,#匹配多个单词 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;</span><br>    <span class="hljs-comment">&lt;!--定义广播交换机中的持久化队列,不存在则自动创建--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_topic_queue_star&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_topic_queue_star&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br>    <span class="hljs-comment">&lt;!--定义广播交换机中的持久化队列,不存在则自动创建--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_topic_queue_well&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_topic_queue_well&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br>    <span class="hljs-comment">&lt;!--定义广播交换机中的持久化队列,不存在则自动创建--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:queue</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_topic_queue_well2&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_topic_queue_well2&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:topic-exchange</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;spring_topic_exchange&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;spring_topic_exchange&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:bindings</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:binding</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">&quot;atguigu.*&quot;</span> <span class="hljs-attr">queue</span>=<span class="hljs-string">&quot;spring_topic_queue_star&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:binding</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">&quot;atguigu.#&quot;</span> <span class="hljs-attr">queue</span>=<span class="hljs-string">&quot;spring_topic_queue_well&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:binding</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">&quot;guigu.#&quot;</span> <span class="hljs-attr">queue</span>=<span class="hljs-string">&quot;spring_topic_queue_well2&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">rabbit:bindings</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">rabbit:topic-exchange</span>&gt;</span><br> <br>    <span class="hljs-comment">&lt;!--定义rabbitTemplate对象操作可以在代码中方便发送消息--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:template</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;rabbitTemplate&quot;</span> <span class="hljs-attr">connection-factory</span>=<span class="hljs-string">&quot;connectionFactory&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">beans</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="6-1-4-发送消息"><a href="#6-1-4-发送消息" class="headerlink" title="6.1.4. 发送消息"></a>6.1.4. 发送消息</h3><p>创建测试文件 <code>ProducerTest``.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq;<br> <br><span class="hljs-keyword">import</span> org.junit.Test;<br><span class="hljs-keyword">import</span> org.junit.runner.RunWith;<br><span class="hljs-keyword">import</span> org.springframework.amqp.rabbit.core.RabbitTemplate;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.test.context.ContextConfiguration;<br><span class="hljs-keyword">import</span> org.springframework.test.context.junit4.SpringRunner;<br> <br><span class="hljs-meta">@RunWith(SpringRunner.class)</span><br><span class="hljs-meta">@ContextConfiguration(locations = &quot;classpath:spring-rabbitmq.xml&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerTest</span> </span>&#123;<br> <br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RabbitTemplate rabbitTemplate;<br> <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 只发队列消息</span><br><span class="hljs-comment">     * 默认交换机类型为 direct</span><br><span class="hljs-comment">     * 交换机的名称为空,路由键为队列的名称</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">queueTest</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">//路由键与队列同名</span><br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_queue&quot;</span>, <span class="hljs-string">&quot;只发队列spring_queue的消息。&quot;</span>);<br>    &#125;<br> <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 发送广播</span><br><span class="hljs-comment">     * 交换机类型为 fanout</span><br><span class="hljs-comment">     * 绑定到该交换机的所有队列都能够收到消息</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fanoutTest</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">/**</span><br><span class="hljs-comment">         * 参数1：交换机名称</span><br><span class="hljs-comment">         * 参数2：路由键名（广播设置为空）</span><br><span class="hljs-comment">         * 参数3：发送的消息内容</span><br><span class="hljs-comment">         */</span><br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_fanout_exchange&quot;</span>, <span class="hljs-string">&quot;&quot;</span>, <span class="hljs-string">&quot;发送到spring_fanout_exchange交换机的广播消息&quot;</span>);<br>    &#125;<br> <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 通配符</span><br><span class="hljs-comment">     * 交换机类型为 topic</span><br><span class="hljs-comment">     * 匹配路由键的通配符,*表示一个单词,#表示多个单词</span><br><span class="hljs-comment">     * 绑定到该交换机的匹配队列能够收到对应消息</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">topicTest</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">/**</span><br><span class="hljs-comment">         * 参数1：交换机名称</span><br><span class="hljs-comment">         * 参数2：路由键名</span><br><span class="hljs-comment">         * 参数3：发送的消息内容</span><br><span class="hljs-comment">         */</span><br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_topic_exchange&quot;</span>, <span class="hljs-string">&quot;atguigu.bj&quot;</span>, <span class="hljs-string">&quot;发送到spring_topic_exchange交换机atguigu.bj的消息&quot;</span>);<br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_topic_exchange&quot;</span>, <span class="hljs-string">&quot;atguigu.bj.1&quot;</span>, <span class="hljs-string">&quot;发送到spring_topic_exchange交换机atguigu.bj.1的消息&quot;</span>);<br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_topic_exchange&quot;</span>, <span class="hljs-string">&quot;atguigu.bj.2&quot;</span>, <span class="hljs-string">&quot;发送到spring_topic_exchange交换机atguigu.bj.2的消息&quot;</span>);<br>        rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;spring_topic_exchange&quot;</span>, <span class="hljs-string">&quot;guigu.cn&quot;</span>, <span class="hljs-string">&quot;发送到spring_topic_exchange交换机guigu.cn的消息&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="6-2-搭建消费者工程"><a href="#6-2-搭建消费者工程" class="headerlink" title="6.2. 搭建消费者工程"></a>6.2. 搭建消费者工程</h2><h3 id="6-2-1-创建工程spring-rabbitmq-consumer"><a href="#6-2-1-创建工程spring-rabbitmq-consumer" class="headerlink" title="6.2.1. 创建工程spring-rabbitmq-consumer"></a>6.2.1. 创建工程spring-rabbitmq-consumer</h3><h3 id="6-2-2-添加依赖"><a href="#6-2-2-添加依赖" class="headerlink" title="6.2.2. 添加依赖"></a>6.2.2. 添加依赖</h3><p>修改pom.xml文件内容为如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.atguigu<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-rabbitmq-consumer<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-context<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.7.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.amqp<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-rabbit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.1.8.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.12<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.1.7.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br> <br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br>    <br>     <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.8.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="6-2-3-配置整合"><a href="#6-2-3-配置整合" class="headerlink" title="6.2.3. 配置整合"></a>6.2.3. 配置整合</h3><p>创建<code>rabbitmq.properties</code>连接参数等配置文件；</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">rabbitmq.host</span>=<span class="hljs-string">192.168.137.118</span><br><span class="hljs-meta">rabbitmq.port</span>=<span class="hljs-string">5672</span><br><span class="hljs-meta">rabbitmq.username</span>=<span class="hljs-string">admin</span><br><span class="hljs-meta">rabbitmq.password</span>=<span class="hljs-string">123456</span><br><span class="hljs-meta">rabbitmq.virtual-host</span>=<span class="hljs-string">/</span><br></code></pre></td></tr></table></figure>

<p>创建<code>spring-rabbitmq.xml</code> 整合配置文件；</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">beans</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/beans&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:context</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/context&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xmlns:rabbit</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/rabbit&quot;</span></span><br><span class="hljs-tag">       <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://www.springframework.org/schema/beans</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/context</span></span><br><span class="hljs-string"><span class="hljs-tag">       https://www.springframework.org/schema/context/spring-context.xsd</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/rabbit</span></span><br><span class="hljs-string"><span class="hljs-tag">       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--加载配置文件--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">context:property-placeholder</span> <span class="hljs-attr">location</span>=<span class="hljs-string">&quot;classpath:rabbitmq.properties&quot;</span>/&gt;</span><br> <br>    <span class="hljs-comment">&lt;!-- 定义rabbitmq connectionFactory --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:connection-factory</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;connectionFactory&quot;</span> <span class="hljs-attr">host</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.host&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">port</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.port&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">username</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.username&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">password</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.password&#125;&quot;</span></span><br><span class="hljs-tag">                               <span class="hljs-attr">virtual-host</span>=<span class="hljs-string">&quot;$&#123;rabbitmq.virtual-host&#125;&quot;</span>/&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;springQueueListener&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.SpringQueueListener&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;fanoutListener1&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.FanoutListener1&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;fanoutListener2&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.FanoutListener2&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;topicListenerStar&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.TopicListenerStar&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;topicListenerWell&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.TopicListenerWell&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;topicListenerWell2&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;com.atguigu.rabbitmq.listener.TopicListenerWell2&quot;</span>/&gt;</span><br> <br>    <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener-container</span> <span class="hljs-attr">connection-factory</span>=<span class="hljs-string">&quot;connectionFactory&quot;</span> <span class="hljs-attr">auto-declare</span>=<span class="hljs-string">&quot;true&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;springQueueListener&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_queue&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;fanoutListener1&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_fanout_queue_1&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;fanoutListener2&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_fanout_queue_2&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;topicListenerStar&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_topic_queue_star&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;topicListenerWell&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_topic_queue_well&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">rabbit:listener</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;topicListenerWell2&quot;</span> <span class="hljs-attr">queue-names</span>=<span class="hljs-string">&quot;spring_topic_queue_well2&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">rabbit:listener-container</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">beans</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="6-2-4-消息监听器"><a href="#6-2-4-消息监听器" class="headerlink" title="6.2.4. 消息监听器"></a>6.2.4. 消息监听器</h3><h4 id="1）队列监听器"><a href="#1）队列监听器" class="headerlink" title="1）队列监听器"></a>1）队列监听器</h4><p>创建<code>SpringQueueListener.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.rabbitmq.listener;<br> <br><span class="hljs-keyword">import</span> org.springframework.amqp.core.Message;<br><span class="hljs-keyword">import</span> org.springframework.amqp.core.MessageListener;<br> <br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SpringQueueListener</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>添加一个测试类，进行测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">import</span> org.junit.Test;<br><span class="hljs-keyword">import</span> org.junit.runner.RunWith;<br><span class="hljs-keyword">import</span> org.springframework.test.context.ContextConfiguration;<br><span class="hljs-keyword">import</span> org.springframework.test.context.junit4.SpringJUnit4ClassRunner;<br> <br><span class="hljs-meta">@RunWith(SpringJUnit4ClassRunner.class)</span><br><span class="hljs-meta">@ContextConfiguration(locations = &quot;classpath:spring-rabbitmq.xml&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsumerTest</span> </span>&#123;<br> <br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">test1</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">boolean</span> flag = <span class="hljs-keyword">true</span>;<br>        <span class="hljs-keyword">while</span> (flag)&#123;<br> <br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="2）广播监听器1"><a href="#2）广播监听器1" class="headerlink" title="2）广播监听器1"></a>2）广播监听器1</h4><p>创建 <code>FanoutListener1``.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FanoutListener1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;广播监听器1：接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="3）广播监听器2"><a href="#3）广播监听器2" class="headerlink" title="3）广播监听器2"></a>3）广播监听器2</h4><p>创建 <code>FanoutListener2.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FanoutListener2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;广播监听器2：接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="4）星号通配符监听器"><a href="#4）星号通配符监听器" class="headerlink" title="4）星号通配符监听器"></a>4）星号通配符监听器</h4><p>创建<code>TopicListenerStar.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TopicListenerStar</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;通配符*监听器：接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="5）井号通配符监听器"><a href="#5）井号通配符监听器" class="headerlink" title="5）井号通配符监听器"></a>5）井号通配符监听器</h4><p>创建<code>TopicListenerWell.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TopicListenerWell</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;通配符#监听器：接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="6）井号通配符监听器2"><a href="#6）井号通配符监听器2" class="headerlink" title="6）井号通配符监听器2"></a>6）井号通配符监听器2</h4><p>创建<code>TopicListenerWell2.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TopicListenerWell2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MessageListener</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMessage</span><span class="hljs-params">(Message message)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            String msg = <span class="hljs-keyword">new</span> String(message.getBody(), <span class="hljs-string">&quot;utf-8&quot;</span>);<br> <br>            System.out.printf(<span class="hljs-string">&quot;通配符#监听器2：接收路由名称为：%s,路由键为：%s,队列名为：%s的消息：%s \n&quot;</span>,<br>                    message.getMessageProperties().getReceivedExchange(),<br>                    message.getMessageProperties().getReceivedRoutingKey(),<br>                    message.getMessageProperties().getConsumerQueue(),<br>                    msg);<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="7-RabbitMQ集成微服务"><a href="#7-RabbitMQ集成微服务" class="headerlink" title="7 RabbitMQ集成微服务"></a>7 RabbitMQ集成微服务</h1><h2 id="7-1-RabbitMQ与SpringBoot整合"><a href="#7-1-RabbitMQ与SpringBoot整合" class="headerlink" title="7.1 RabbitMQ与SpringBoot整合"></a>7.1 RabbitMQ与SpringBoot整合</h2><h3 id="7-1-1-搭建生产者工程"><a href="#7-1-1-搭建生产者工程" class="headerlink" title="7.1.1. 搭建生产者工程"></a>7.1.1. 搭建生产者工程</h3><p>实现步骤：</p>
<ol>
<li>创建生产者SpringBoot工程</li>
<li>引入依赖坐标</li>
<li>编写yml配置，基本信息配置</li>
<li>定义交换机，队列以及绑定关系的配置类</li>
<li>注入RabbitTemplate，调用方法，完成消息发送</li>
</ol>
<h4 id="7-1-1-1-创建工程"><a href="#7-1-1-1-创建工程" class="headerlink" title="7.1.1.1. 创建工程"></a>7.1.1.1. 创建工程</h4><p>项目名字 ：<code>producer-springboot</code></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image092.gif?versionId=CAEQKRiBgMCbhKyA.hciIGVhODk4YzBiODc5NjRjNzNhYTYxZDI1ZTgwMjM0N2Y3" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="7-1-1-2-添加依赖"><a href="#7-1-1-2-添加依赖" class="headerlink" title="7.1.1.2. 添加依赖"></a>7.1.1.2. 添加依赖</h4><p>修改pom.xml文件内容为如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">1. 父工程依赖</span><br><span class="hljs-comment">--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.3.6.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span><br> <br><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--2. rabbitmq--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-amqp<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="7-1-1-3-配置整合"><a href="#7-1-1-3-配置整合" class="headerlink" title="7.1.1.3. 配置整合"></a>7.1.1.3. 配置整合</h4><p>创建<code>application.yml</code>连接参数等配置文件；</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span> <br>  <span class="hljs-attr">rabbitmq:</span> <br>    <span class="hljs-attr">host:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.137</span><span class="hljs-number">.118</span><br>    <span class="hljs-attr">port:</span> <span class="hljs-number">5672</span><br>    <span class="hljs-attr">username:</span> <span class="hljs-string">admin</span><br>    <span class="hljs-attr">password:</span> <span class="hljs-number">123456</span><br>    <span class="hljs-attr">virtual-host:</span> <span class="hljs-string">/</span><br></code></pre></td></tr></table></figure>

<h4 id="7-1-1-4-创建配置类"><a href="#7-1-1-4-创建配置类" class="headerlink" title="7.1.1.4. 创建配置类"></a>7.1.1.4. 创建配置类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.config;<br> <br><span class="hljs-keyword">import</span> org.springframework.amqp.core.*;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Qualifier;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br> <br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RabbitMQConfig</span> </span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String EXCHANGE_NAME = <span class="hljs-string">&quot;boot_topic_exchange&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String QUEUE_NAME = <span class="hljs-string">&quot;boot_queue&quot;</span>;<br> <br>    <span class="hljs-comment">// 1 交换机</span><br>    <span class="hljs-meta">@Bean(&quot;bootExchange&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Exchange <span class="hljs-title">bootExchange</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(<span class="hljs-keyword">true</span>).build();<br>    &#125;<br>    <span class="hljs-comment">//2.Queue 队列</span><br>    <span class="hljs-meta">@Bean(&quot;bootQueue&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Queue <span class="hljs-title">bootQueue</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> QueueBuilder.durable(QUEUE_NAME).build();<br>    &#125;<br>    <span class="hljs-comment">//3. 队列和交互机绑定关系 Binding</span><br>    <span class="hljs-comment">/*</span><br><span class="hljs-comment">        1. 知道哪个队列</span><br><span class="hljs-comment">        2. 知道哪个交换机</span><br><span class="hljs-comment">        3. routing key</span><br><span class="hljs-comment">        noargs()：表示不指定参数</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Binding <span class="hljs-title">bindQueueExchange</span><span class="hljs-params">(<span class="hljs-meta">@Qualifier(&quot;bootQueue&quot;)</span> Queue queue,</span></span><br><span class="hljs-params"><span class="hljs-function">                                     <span class="hljs-meta">@Qualifier(&quot;bootExchange&quot;)</span> Exchange exchange)</span></span>&#123;<br>        <span class="hljs-keyword">return</span> BindingBuilder.bind(queue).to(exchange).with(<span class="hljs-string">&quot;boot.#&quot;</span>).noargs();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="7-1-1-5-创建入口类"><a href="#7-1-1-5-创建入口类" class="headerlink" title="7.1.1.5. 创建入口类"></a>7.1.1.5. 创建入口类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu;<br> <br><span class="hljs-keyword">import</span> org.springframework.boot.SpringApplication;<br><span class="hljs-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;<br> <br><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerApplication</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        SpringApplication.run(ProducerApplication.class);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="7-1-1-6-发送消息"><a href="#7-1-1-6-发送消息" class="headerlink" title="7.1.1.6. 发送消息"></a>7.1.1.6. 发送消息</h4><p>创建测试文件 <code>com.atguigu.ProducerTest.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu;<br> <br><span class="hljs-keyword">import</span> com.atguigu.config.RabbitMQConfig;<br><span class="hljs-keyword">import</span> org.junit.Test;<br><span class="hljs-keyword">import</span> org.junit.runner.RunWith;<br><span class="hljs-keyword">import</span> org.springframework.amqp.rabbit.core.RabbitTemplate;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.boot.test.context.SpringBootTest;<br><span class="hljs-keyword">import</span> org.springframework.test.context.junit4.SpringRunner;<br> <br><span class="hljs-meta">@SpringBootTest</span><br><span class="hljs-meta">@RunWith(SpringRunner.class)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerTest</span> </span>&#123;<br> <br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RabbitTemplate rabbitTemplate;<br> <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 第一个参数：交换机名字</span><br><span class="hljs-comment">     * 第二个参数：routingKey</span><br><span class="hljs-comment">     * 第三个参数：发送的消息</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSend</span><span class="hljs-params">()</span></span>&#123;<br>        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME,<span class="hljs-string">&quot;boot.haha&quot;</span>,<span class="hljs-string">&quot;mq hello&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行测试类,发送消息</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image094.gif?versionId=CAEQKRiBgMCYhKyA.hciIGRmZGNhZTBlNDliZDQ0Yzg4NmRjNWM1NDNlNTg2MTg2" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="7-1-2-搭建消费者工程"><a href="#7-1-2-搭建消费者工程" class="headerlink" title="7.1.2. 搭建消费者工程"></a>7.1.2. 搭建消费者工程</h3><p>实现步骤</p>
<ol>
<li>创建消费者SpringBoot工程</li>
<li>引入start,依赖坐标</li>
<li>编写yml配置,基本信息配置</li>
<li>定义监听类,使用@RabbitListener注解完成队列监听。</li>
</ol>
<h4 id="7-1-2-1-创建工程"><a href="#7-1-2-1-创建工程" class="headerlink" title="7.1.2.1. 创建工程"></a>7.1.2.1. 创建工程</h4><p>创建项目 <code>consumer-springboot</code></p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image096.gif?versionId=CAEQKRiBgICRhKyA.hciIDYxMmQyYTg2ZjRmODRkODBhMjFkZGI3MTA4ZDRlNmEy" srcset="/img/loading.gif" lazyload alt="img"></p>
<h4 id="7-1-2-2-添加依赖"><a href="#7-1-2-2-添加依赖" class="headerlink" title="7.1.2.2. 添加依赖"></a>7.1.2.2. 添加依赖</h4><p>修改pom.xml文件内容为如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.3.6.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--RabbitMQ 启动依赖--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-amqp<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h4 id="7-1-2-3-配置整合"><a href="#7-1-2-3-配置整合" class="headerlink" title="7.1.2.3. 配置整合"></a>7.1.2.3. 配置整合</h4><p>创建application.yml连接参数等配置文件；</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span> <br>  <span class="hljs-attr">rabbitmq:</span> <br>    <span class="hljs-attr">host:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.137</span><span class="hljs-number">.118</span><br>    <span class="hljs-attr">port:</span> <span class="hljs-number">5672</span><br>    <span class="hljs-attr">username:</span> <span class="hljs-string">admin</span><br>    <span class="hljs-attr">password:</span> <span class="hljs-number">123456</span><br>    <span class="hljs-attr">virtual-host:</span> <span class="hljs-string">/</span><br></code></pre></td></tr></table></figure>



<h4 id="7-1-2-4-消息监听器"><a href="#7-1-2-4-消息监听器" class="headerlink" title="7.1.2.4. 消息监听器"></a>7.1.2.4. 消息监听器</h4><p>队列监听器</p>
<p>创建 <code>com.atguigu.listener.RabbimtMQListener</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu.listener;<br> <br><span class="hljs-keyword">import</span> org.springframework.amqp.core.Message;<br><span class="hljs-keyword">import</span> org.springframework.amqp.rabbit.annotation.RabbitListener;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br> <br><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RabbimtMQListener</span> </span>&#123;<br>    <span class="hljs-meta">@RabbitListener(queues = &quot;boot_queue&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">listenerQueue</span><span class="hljs-params">(Message message)</span></span>&#123;<br>        System.out.println(<span class="hljs-keyword">new</span> String(message.getBody()));<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>创建入口类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.atguigu;<br> <br><span class="hljs-keyword">import</span> org.springframework.boot.SpringApplication;<br><span class="hljs-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;<br> <br><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsumerApplication</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        SpringApplication.run(ConsumerApplication.class, args);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<p>运行applicaion：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image098.gif?versionId=CAEQKRiBgMCShKyA.hciIGFiODYzNTE3NDZjOTRiZDViNTFiZWJhMTkzMDc4OTZk" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>小结：</p>
<p>l SpringBoot提供了快速整合RabbitMQ的方式</p>
<p>l 基本信息在yml中配置,队列交互机以及绑定关系在配置类中使用Bean的方式配置</p>
<p>l 生产端直接注入RabbitTemplate完成消息发送</p>
<p>l 消费端直接使用@RabbitListener完成消息接收</p>
<h4 id="7-1-2-5-基于注解的消息监听器-常用"><a href="#7-1-2-5-基于注解的消息监听器-常用" class="headerlink" title="7.1.2.5. 基于注解的消息监听器(常用)"></a>7.1.2.5. 基于注解的消息监听器(常用)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RabbitListener(bindings = @QueueBinding(</span><br><span class="hljs-meta">        value = @Queue(value = 队列名, durable = &quot;true&quot;),</span><br><span class="hljs-meta">        exchange = @Exchange(value = 交换机名字),</span><br><span class="hljs-meta">        key = &#123;路由值&#125;</span><br><span class="hljs-meta">))</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">send</span><span class="hljs-params">(Channel channel,Message message,VO vo)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>    log.info(<span class="hljs-string">&quot;SmsReceiver 消息监听&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="8-RabbitMQ高级特性"><a href="#8-RabbitMQ高级特性" class="headerlink" title="8 RabbitMQ高级特性"></a>8 RabbitMQ高级特性</h1><h2 id="8-1-消息的可靠投递"><a href="#8-1-消息的可靠投递" class="headerlink" title="8.1 消息的可靠投递"></a>8.1 消息的可靠投递</h2><p>在使用 RabbitMQ 的时候，作为消息发送方希望<strong>杜绝任何消息丢失</strong>或者<strong>投递失败</strong>场景。RabbitMQ 为我们提供了<strong>两种方式</strong>用来<strong>控制消息的投递可靠性模式</strong>。</p>
<p>·     <strong>confirm</strong> <strong>确认模式</strong></p>
<p>·     <strong>return</strong> <strong>退回模式</strong></p>
<p>rabbitmq 整个消息投递的路径为：</p>
<p>producer—&gt;rabbitmq broker—&gt;exchange—&gt;queue—&gt;consumer</p>
<p>l消息从 producer 到 exchange 则会返回一个 confirmCallback 。</p>
<p>l消息从 exchange–&gt;queue 投递失败则会返回一个 returnCallback 。</p>
<p>我们将利用这两个 callback 控制消息的可靠性投递</p>
<h3 id="8-1-1-提供者代码实现-这部分代码是在生产者端实现的"><a href="#8-1-1-提供者代码实现-这部分代码是在生产者端实现的" class="headerlink" title="8.1.1 提供者代码实现(这部分代码是在生产者端实现的)"></a>8.1.1 提供者代码实现(这部分代码是在生产者端实现的)</h3><p>在rabbit-mq模块中创建MqAckConfig</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image108.gif?versionId=CAEQKRiBgICQgqyA.hciIDkxMWMyMTBlZTk3NjQyYWQ5ZTkyNjI0ZmIwZjk3MmE5" srcset="/img/loading.gif" lazyload alt="img"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MqAckConfig</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">RabbitTemplate</span>.<span class="hljs-title">ConfirmCallback</span>, <span class="hljs-title">RabbitTemplate</span>.<span class="hljs-title">ReturnCallback</span> </span>&#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    RabbitTemplate rabbitTemplate;<br><br>    <span class="hljs-meta">@PostConstruct</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">()</span> </span>&#123;<br>        rabbitTemplate.setConfirmCallback(<span class="hljs-keyword">this</span>);<br>        rabbitTemplate.setReturnCallback(<span class="hljs-keyword">this</span>);<br>    &#125;<br><br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">confirm</span><span class="hljs-params">(<span class="hljs-meta">@Nullable</span> CorrelationData correlationData, <span class="hljs-keyword">boolean</span> ack, <span class="hljs-meta">@Nullable</span> String error)</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;消息的发送情况&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">returnedMessage</span><span class="hljs-params">(Message message, <span class="hljs-keyword">int</span> code, String codeMessage, String exchange, String routing)</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;消息的投递情况&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在rabbit-test测试服务中添加配置</p>
<p>application.properties</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.rabbitmq.publisher-returns</span>=<span class="hljs-string">true</span><br><span class="hljs-meta">spring.rabbitmq.publisher-confirm-type</span>=<span class="hljs-string">simple</span><br></code></pre></td></tr></table></figure>

<h3 id="8-1-2-消息的可靠投递小结"><a href="#8-1-2-消息的可靠投递小结" class="headerlink" title="8.1.2 消息的可靠投递小结"></a>8.1.2 消息的可靠投递小结</h3><p>·     设置 <code>ConnectionFactory</code>的<code>publisher-confirms=&quot;true&quot;</code> 开启 确认模式。</p>
<p>·     使用 <code>rabbitTemplate.setConfirmCallback</code> 设置回调函数。当消息发送到 <code>exchange</code> 后回调 <code>confirm</code> 方法。在方法中判断 <code>ack</code>，如果为<code>true</code>，则发送成功，如果为<code>false</code>，则发送失败，需要处理。</p>
<p>·     设置 <code>ConnectionFactory</code> 的 <code>publisher-returns=&quot;true&quot;</code> 开启 退回模式。</p>
<p>·     使用 <code>rabbitTemplate.setReturnCallback</code> 设置退回函数，当消息从<code>exchange</code> 路由到 <code>queue</code> 失败后，如果设置了 <code>rabbitTemplate.setMandatory(true)</code> 参数，则会将消息退回给 <code>producer</code>并执行回调函数<code>returnedMessage</code></p>
<h3 id="8-1-3-Consumer-Ack（消息事务）"><a href="#8-1-3-Consumer-Ack（消息事务）" class="headerlink" title="8.1.3 Consumer Ack（消息事务）"></a>8.1.3 Consumer Ack（消息事务）</h3><p>ack指Acknowledge，确认。 表示消费端收到消息后的确认方式。</p>
<p>有二种确认方式：</p>
<p>·     自动确认：acknowledge=“none” 默认</p>
<p>·     手动确认：acknowledge=“manual”</p>
<p>其中自动确认是指，当消息一旦被Consumer接收到，则自动确认收到，并将相应 message 从 RabbitMQ 的消息缓存中移除。但是在实际业务处理中，很可能消息接收到，业务处理出现异常，那么该消息就会丢失。</p>
<p>如果设置了手动确认方式，则需要在业务处理成功后，调用channel.basicAck()，手动签收，如果出现异常，则调用channel.basicNack()方法，让其自动重新发送消息。</p>
<h4 id="8-1-3-1-自动确认"><a href="#8-1-3-1-自动确认" class="headerlink" title="8.1.3.1 自动确认"></a>8.1.3.1 自动确认</h4><p>application.properties</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.rabbitmq.listener.simple.acknowledge-mode</span>=<span class="hljs-string">auto</span><br><span class="hljs-meta">spring.rabbitmq.listener.direct.acknowledge-mode</span>=<span class="hljs-string">auto</span><br></code></pre></td></tr></table></figure>

<h4 id="8-1-3-2-手动确认"><a href="#8-1-3-2-手动确认" class="headerlink" title="8.1.3.2 手动确认"></a>8.1.3.2 手动确认</h4><p>application.properties</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.rabbitmq.listener.simple.acknowledge-mode</span>=<span class="hljs-string">manual</span><br><span class="hljs-meta">spring.rabbitmq.listener.direct.acknowledge-mode</span>=<span class="hljs-string">manual</span><br></code></pre></td></tr></table></figure>

<p>相关代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"> <br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">a</span><span class="hljs-params">(Channel channel , Message message, String messageStr)</span></span>&#123;<br>    System.out.println(messageStr);<br>    String s = <span class="hljs-keyword">new</span> String(message.getBody());<br>    <span class="hljs-comment">// 消费完成后，确认commit</span><br>    channel.basicAck(message.getMessageProperties().getDeliveryTag(),<span class="hljs-keyword">false</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>Consumer Ack</strong> <strong>小结</strong></p>
<p>commit提交确认：</p>
<p>如果在消费端没有出现异常，则调用channel.basicAck(deliveryTag，true);方法确认签收消息，如果出现异常</p>
<p>Rollback回滚消息：</p>
<p>则在catch中调用 basicNack，拒绝消息，让MQ重新发送消息，</p>
<h2 id="8-2-消费端限流"><a href="#8-2-消费端限流" class="headerlink" title="8.2 消费端限流"></a>8.2 消费端限流</h2><p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image110.gif?versionId=CAEQKRiBgMCMgqyA.hciIGM3ZTcxN2Y5YThkZjQ3ODliNjg2ZmQ1YWZkMzBhMWM0" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>application.properties</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.rabbitmq.listener.simple.prefetch</span>=<span class="hljs-string">1</span><br><span class="hljs-meta">spring.rabbitmq.listener.direct.prefetch</span>=<span class="hljs-string">1</span><br></code></pre></td></tr></table></figure>

<p>小结：</p>
<p>prefetch = 1,表示消费端每次从mq拉去一条消息来消费,直到手动确认消费完毕后,才会继续拉取下一条消息</p>
<h2 id="8-3-TTL"><a href="#8-3-TTL" class="headerlink" title="8.3 TTL"></a>8.3 TTL</h2><p>TTL 全称 Time To Live（存活时间/过期时间）。</p>
<p>当消息到达存活时间后，还没有被消费，会被自动清除。</p>
<p>RabbitMQ可以对消息设置过期时间，也可以对整个队列（Queue）设置过期时间。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image112.gif?versionId=CAEQKRiBgMCNgqyA.hciIDk3MjgxMjdiMjJiMzQ4ZWNiYTUzNDYyMzJjYTk5NjFj" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="8-3-1-控制后台演示消息过期"><a href="#8-3-1-控制后台演示消息过期" class="headerlink" title="8.3.1 控制后台演示消息过期"></a>8.3.1 控制后台演示消息过期</h3><p>① 修改管理后台界面，增加队列</p>
<p>参数：表示过期时间，单位毫秒 ，10000表示10秒</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image114.gif?versionId=CAEQKRiBgMCDgqyA.hciIDlkYjUyMDRmZGU3ZDQzODI5NjcyMGEwMzgyZGY2OTcx" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>② 增加交换机</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image116.gif?versionId=CAEQKRiBgMCCgqyA.hciIDhhMGY2MzNmM2ZhNzRlNGNhZmZkMGYyMzAwMTMyM2Mw" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>③ 绑定队列</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image118.gif?versionId=CAEQKRiBgIDugayA.hciIDdhZTUwODE0OGJjZDQ3NDk4ODgzNjM0ZmZkZWU2NmNk" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>④ 发送消息</p>
<p>Delivery mode：2-Persistent表示需要进行持久化</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image120.gif?versionId=CAEQKRiBgMC9gKyA.hciIDBjZjE5M2Q1NDM2YzQ0OWY4NGVlNmMyZDAyNDI0YTYx" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>⑤ 查看消息，可以看到消息，但十秒之后，消息自动消失，因为我们设置了十秒消息过期</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image122.gif?versionId=CAEQKRiBgIC6gKyA.hciIGQ5NzliMWI1ODVmOTRjZDI5OTJhZTY5MDY3YTUzZjk0" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="8-3-2-代码实现"><a href="#8-3-2-代码实现" class="headerlink" title="8.3.2 代码实现"></a>8.3.2 代码实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"> <span class="hljs-comment">/**</span><br><span class="hljs-comment"> * TTL：过期时间</span><br><span class="hljs-comment"> *  1. 队列统一过期</span><br><span class="hljs-comment"> *  2. 消息单独过期</span><br><span class="hljs-comment"> * 如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准。</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testMessageTtl</span><span class="hljs-params">()</span> </span>&#123;<br>    <span class="hljs-comment">// 消息后处理对象,设置一些消息的参数信息</span><br>    MessagePostProcessor messagePostProcessor = <span class="hljs-keyword">new</span> MessagePostProcessor() &#123;<br> <br>        <span class="hljs-meta">@Override</span><br>        <span class="hljs-function"><span class="hljs-keyword">public</span> Message <span class="hljs-title">postProcessMessage</span><span class="hljs-params">(Message message)</span> <span class="hljs-keyword">throws</span> AmqpException </span>&#123;<br>            <span class="hljs-comment">//1.设置message的信息</span><br>            <span class="hljs-comment">// 第二个方法：消息的过期时间 ,5秒之后过期</span><br>            message.getMessageProperties().setExpiration(<span class="hljs-string">&quot;5000&quot;</span>);<br>            <span class="hljs-comment">//2.返回该消息</span><br>            <span class="hljs-keyword">return</span> message;<br>        &#125;<br>    &#125;;<br> <br>    <span class="hljs-comment">//消息单独过期</span><br>    rabbitTemplate.convertAndSend(<span class="hljs-string">&quot;test_exchange_ttl&quot;</span>,<span class="hljs-string">&quot;ttl.hehe&quot;</span>,<span class="hljs-string">&quot;message ttl....&quot;</span>,messagePostProcessor);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行程序,查看后台管理系统</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image124.gif?versionId=CAEQKRiBgICpgKyA.hciIGVlZTYwZGYzY2ZjYjQ5ODI5OWVlMWExMTBjODgxZDIw" srcset="/img/loading.gif" lazyload alt="img"></p>
<h2 id="8-4-死信队列"><a href="#8-4-死信队列" class="headerlink" title="8.4 死信队列"></a>8.4 死信队列</h2><p>死信队列，英文缩写：DLX 。DeadLetter Exchange（死信交换机），当消息成为Dead message后，可以被重新发送到另一个交换机，这个交换机就是DLX。</p>
<p><strong>什么是死信队列</strong></p>
<p>先从概念解释上搞清楚这个定义，死信，顾名思义就是无法被消费的消息，字面意思可以这样理解，一般来说，producer将消息投递到broker或者直接到queue里了，consumer从queue取出消息进行消费，但某些时候由于特定的原因导致queue中的某些消息无法被消费，这样的消息如果没有后续的处理，就变成了死信，有死信，自然就有了死信队列；</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image126.gif?versionId=CAEQKRiDgICcgKyA.hciIDY4NzllNTcwM2U0NTRiYjU5NzgwZjIzMjQ0ODMwOWI1" srcset="/img/loading.gif" lazyload alt="img"></p>
<p><strong>消息成为死信的三种情况：</strong></p>
<ol>
<li><p>队列消息数量到达限制；比如队列最大只能存储10条消息，而发了11条消息，根据先进先出，最先发的消息会进入死信队列。</p>
</li>
<li><p>消费者拒接消费消息，basicNack/basicReject，并且不把消息重新放入原目标队列，requeue=false；</p>
</li>
<li><p>原队列存在消息过期设置，消息到达超时时间未被消费；</p>
</li>
</ol>
<p><strong>死信的处理方式</strong></p>
<p>死信的产生既然不可避免，那么就需要从实际的业务角度和场景出发，对这些死信进行后续的处理，常见的处理方式大致有下面几种，</p>
<p>① 丢弃，如果不是很重要，可以选择丢弃</p>
<p>② 记录死信入库，然后做后续的业务分析或处理</p>
<p>③ 通过死信队列，由负责监听死信的应用程序进行处理</p>
<p>综合来看，更常用的做法是第三种，即通过死信队列，将产生的死信通过程序的配置路由到指定的死信队列，然后应用监听死信队列，对接收到的死信做后续的处理，</p>
<p><strong>队列绑定死信交换机：</strong></p>
<p>给队列设置参数： x-dead-letter-exchange 和 x-dead-letter-routing-key</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image128.gif?versionId=CAEQKRiBgICfgKyA.hciIGI4Y2NlNGFmZTNhMDQ5ZjhiZmM2ZGY4YWRhNmIxMGU2" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="8-4-1-代码实现"><a href="#8-4-1-代码实现" class="headerlink" title="8.4.1 代码实现"></a>8.4.1 代码实现</h3><p>新建配置文件(类),DeadLetterMqConfig</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image130.gif?versionId=CAEQKRiBgMCMgKyA.hciIGU2ZWEyMzM4MGUxMDQ2YmZiMTQxN2FlNDM0MmQzYjlm" srcset="/img/loading.gif" lazyload alt="img"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadLetterMqConfig</span> </span>&#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String exchange_dead = <span class="hljs-string">&quot;exchange.dead&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String routing_dead_1 = <span class="hljs-string">&quot;routing.dead.1&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String routing_dead_2 = <span class="hljs-string">&quot;routing.dead.2&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String queue_dead_1 = <span class="hljs-string">&quot;queue.dead.1&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String queue_dead_2 = <span class="hljs-string">&quot;queue.dead.2&quot;</span>;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 其他队列可以在RabbitListener上面做绑定</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> DirectExchange <span class="hljs-title">exchange</span><span class="hljs-params">()</span> </span>&#123;<br><br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> DirectExchange(exchange_dead, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">null</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Queue <span class="hljs-title">queue1</span><span class="hljs-params">()</span> </span>&#123;<br>        Map&lt;String, Object&gt; arguments = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();<br>        arguments.put(<span class="hljs-string">&quot;x-dead-letter-exchange&quot;</span>, exchange_dead);<br>        arguments.put(<span class="hljs-string">&quot;x-dead-letter-routing-key&quot;</span>, routing_dead_2);<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Queue(queue_dead_1, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">false</span>, arguments);<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Binding <span class="hljs-title">binding</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> BindingBuilder.bind(queue1()).to(exchange()).with(routing_dead_1);<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Queue <span class="hljs-title">queue2</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Queue(queue_dead_2, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">false</span>, <span class="hljs-keyword">null</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Binding <span class="hljs-title">deadBinding</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> BindingBuilder.bind(queue2()).to(exchange()).with(routing_dead_2);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>发送死信息队列，并设置ttl时间，MqServiceImpl类中增加方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendDeadMsg</span><span class="hljs-params">(String exchange_dead, String routing_dead_1, String test)</span> </span>&#123;<br>    System.out.println(<span class="hljs-string">&quot;发送死信消息&quot;</span>);<br>    rabbitTemplate.convertAndSend(exchange_dead,routing_dead_1,test,p-&gt;&#123;<br>        <span class="hljs-comment">// 死信消息的设置，设置ttl(time to live 存活时间)</span><br>        p.getMessageProperties().setExpiration(<span class="hljs-string">&quot;3000&quot;</span>);<span class="hljs-comment">//3秒的ttl</span><br>        <span class="hljs-keyword">return</span> p;<br>    &#125;);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>调用死信方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendDeadMsg</span><span class="hljs-params">()</span> </span>&#123;<br>    mqService.sendDeadMsg(DeadLetterMqConfig.exchange_dead,<span class="hljs-string">&quot;1111&quot;</span>,<span class="hljs-string">&quot;test&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>死信队列小结</strong></p>
<ol>
<li><p>死信交换机和死信队列和普通的没有区别</p>
</li>
<li><p>当消息成为死信后，如果该队列绑定了死信交换机，则消息会被死信交换机重新路由到死信队列</p>
</li>
<li><p>消息成为死信的三种情况：</p>
</li>
</ol>
<ul>
<li>队列消息长度（数量）到达限制；</li>
<li>消费者拒接消费消息，并且不重回队列；</li>
<li>原队列存在消息过期设置，消息到达超时时间未被消费；</li>
</ul>
<h2 id="8-5-延迟队列"><a href="#8-5-延迟队列" class="headerlink" title="8.5 延迟队列"></a>8.5 延迟队列</h2><p>延迟队列存储的对象肯定是对应的延时消息，所谓”延时消息”是指当消息被发送以后，并不想让消费者立即拿到消息，而是等待指定时间后，消费者才拿到这个消息进行消费。</p>
<p>场景：在订单系统中，一个用户下单之后通常有30分钟的时间进行支付，如果30分钟之内没有支付成功，那么这个订单将进行取消处理。这时就可以使用延时队列将订单信息发送到延时队列。</p>
<p>需求：</p>
<ol>
<li><p>下单后，30分钟未支付，取消订单，回滚库存。</p>
</li>
<li><p>新用户注册成功30分钟后，发送短信问候。</p>
</li>
</ol>
<p>实现方式：</p>
<ol>
<li>延迟队列</li>
</ol>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image132.gif?versionId=CAEQKRiBgMCWgKyA.hciIDQ3MjE4NmZiNjE0YzRhMmY4ZjhlNWQ0ZWE1MjBhMmU5" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>很可惜，在RabbitMQ中并未提供延迟队列功能。</p>
<p>但是可以使用：TTL+死信队列 组合实现延迟队列的效果。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image134.gif?versionId=CAEQKRiBgMChgKyA.hciIDZhMTI2MDMzOGUyOTQ3ODE4OGUwNWMwZjY3OGRlMzhh" srcset="/img/loading.gif" lazyload alt="img"></p>
<h3 id="8-5-1-代码实现"><a href="#8-5-1-代码实现" class="headerlink" title="8.5.1 代码实现"></a>8.5.1 代码实现</h3><p>配置文件</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DelayedMqConfig</span> </span>&#123;<br> <br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String exchange_delay = <span class="hljs-string">&quot;exchange.delay&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String routing_delay = <span class="hljs-string">&quot;routing.delay&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String queue_delay_1 = <span class="hljs-string">&quot;queue.delay.1&quot;</span>;<br> <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 队列不要在RabbitListener上面做绑定，否则不会成功，如队列2，必须在此绑定</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br> <br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Queue <span class="hljs-title">delayQeue1</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-comment">// 第一个参数是创建的queue的名字，第二个参数是是否支持持久化</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Queue(queue_delay_1, <span class="hljs-keyword">true</span>);<br>    &#125;<br> <br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> CustomExchange <span class="hljs-title">delayExchange</span><span class="hljs-params">()</span> </span>&#123;<br>        Map&lt;String, Object&gt; args = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();<br>        args.put(<span class="hljs-string">&quot;x-delayed-type&quot;</span>, <span class="hljs-string">&quot;direct&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> CustomExchange(exchange_delay, <span class="hljs-string">&quot;x-delayed-message&quot;</span>, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">false</span>, args);<br>    &#125;<br> <br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Binding <span class="hljs-title">delayBbinding1</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> BindingBuilder.bind(delayQeue1()).to(delayExchange()).with(routing_delay).noargs();<br>    &#125;<br> <br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="8-5-1-1-生产者"><a href="#8-5-1-1-生产者" class="headerlink" title="8.5.1.1 生产者"></a>8.5.1.1 生产者</h4><p>生产者</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"> <br><span class="hljs-meta">@Override</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendDelayMessage</span><span class="hljs-params">(String exchange, String routingKey, String message, <span class="hljs-keyword">int</span> time, TimeUnit seconds)</span> </span>&#123;<br>    rabbitTemplate.convertAndSend(exchange,routingKey,message,processer-&gt;&#123;<br>        <span class="hljs-comment">// 设置消息的延迟时间</span><br>        processer.getMessageProperties().setDelay(<span class="hljs-number">1</span>*<span class="hljs-number">1000</span>*time);<span class="hljs-comment">// ttl时间，默认毫秒</span><br>        <span class="hljs-keyword">return</span> processer;<br>    &#125;);<br>&#125;<br> <br></code></pre></td></tr></table></figure>



<h4 id="8-5-1-2-消费者"><a href="#8-5-1-2-消费者" class="headerlink" title="8.5.1.2 消费者"></a>8.5.1.2 消费者</h4><p>消费者</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"> <br><span class="hljs-meta">@SneakyThrows</span><br><span class="hljs-meta">@RabbitListener(queues = &quot;queue.delay.1&quot;)</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">d</span><span class="hljs-params">(Channel channel, Message message, String c)</span> <span class="hljs-keyword">throws</span> IOException </span>&#123;<br>    System.out.println(<span class="hljs-string">&quot;延迟队列的监听&quot;</span>);<br>    <span class="hljs-keyword">long</span> deliveryTag = message.getMessageProperties().getDeliveryTag();<br>    channel.basicAck(deliveryTag, <span class="hljs-keyword">false</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="9-消息百分百成功投递"><a href="#9-消息百分百成功投递" class="headerlink" title="9 消息百分百成功投递"></a>9 消息百分百成功投递</h1><p>谈到消息的可靠性投递，无法避免的，在实际的工作中会经常碰到，比如一些核心业务需要保障消息不丢失，接下来我们看一个可靠性投递的流程图，说明可靠性投递的概念：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image136.gif?versionId=CAEQKRiBgICVgKyA.hciIDE4ZWM2ZWJhZTE0MTQ4YWQ4YjI3YjBhZjBkNTAwYjkx" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>Step 1： 首先把消息信息(业务数据）存储到数据库中，紧接着，我们再把这个消息记录也存储到一张消息记录表里（或者另外一个同源数据库的消息记录表）</p>
<p>Step 2：发送消息到MQ Broker节点（采用confirm方式发送，会有异步的返回结果）</p>
<p>Step 3、4：生产者端接受MQ Broker节点返回的Confirm确认消息结果，然后进行更新消息记录表里的消息状态。比如默认Status = 0 当收到消息确认成功后，更新为1即可！</p>
<p>Step 5：但是在消息确认这个过程中可能由于网络闪断、MQ Broker端异常等原因导致 回送消息失败或者异常。这个时候就需要发送方（生产者）对消息进行可靠性投递了，保障消息不丢失，100%的投递成功！（有一种极限情况是闪断，Broker返回的成功确认消息，但是生产端由于网络闪断没收到，这个时候重新投递可能会造成消息重复，需要消费端去做幂等处理）所以我们需要有一个定时任务，（比如每5分钟拉取一下处于中间状态的消息，当然这个消息可以设置一个超时时间，比如超过1分钟 Status = 0 ，也就说明了1分钟这个时间窗口内，我们的消息没有被确认，那么会被定时任务拉取出来）</p>
<p>Step 6：接下来我们把中间状态的消息进行重新投递 retry send，继续发送消息到MQ ，当然也可能有多种原因导致发送失败</p>
<p>Step 7：我们可以采用设置最大努力尝试次数，比如投递了3次，还是失败，那么我们可以将最终状态设置为Status = 2 ，最后 交由人工解决处理此类问题（或者把消息转储到失败表中）。</p>
<h2 id="9-1-数据库文件"><a href="#9-1-数据库文件" class="headerlink" title="9.1 数据库文件"></a>9.1 数据库文件</h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-comment">-- Table structure for broker_message_log</span><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `broker_message_log`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `broker_message_log` (<br>  `message_id` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;消息唯一ID&#x27;</span>,<br>  `message` <span class="hljs-type">varchar</span>(<span class="hljs-number">4000</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;消息内容&#x27;</span>,<br>  `try_count` <span class="hljs-type">int</span>(<span class="hljs-number">4</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;0&#x27;</span> COMMENT <span class="hljs-string">&#x27;重试次数&#x27;</span>,<br>  `status` <span class="hljs-type">varchar</span>(<span class="hljs-number">10</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;&#x27;</span> COMMENT <span class="hljs-string">&#x27;消息投递状态 0投递中,1投递成功,2投递失败&#x27;</span>,<br>  `next_retry` <span class="hljs-type">timestamp</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;0000-00-00 00：00：00&#x27;</span> <span class="hljs-keyword">ON</span> UPDATE <span class="hljs-built_in">CURRENT_TIMESTAMP</span> COMMENT <span class="hljs-string">&#x27;下一次重试时间&#x27;</span>,<br>  `create_time` <span class="hljs-type">timestamp</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;0000-00-00 00：00：00&#x27;</span> <span class="hljs-keyword">ON</span> UPDATE <span class="hljs-built_in">CURRENT_TIMESTAMP</span>,<br>  `update_time` <span class="hljs-type">timestamp</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;0000-00-00 00：00：00&#x27;</span> <span class="hljs-keyword">ON</span> UPDATE <span class="hljs-built_in">CURRENT_TIMESTAMP</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`message_id`)<br>) ENGINE<span class="hljs-operator">=</span>InnoDB <span class="hljs-keyword">DEFAULT</span> CHARSET<span class="hljs-operator">=</span>utf8;<br> <br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-comment">-- Table structure for t_order</span><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `t_order`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `t_order` (<br>  `id` <span class="hljs-type">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> AUTO_INCREMENT,<br>  `name` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  `message_id` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`id`)<br>) ENGINE<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2018091102</span> <span class="hljs-keyword">DEFAULT</span> CHARSET<span class="hljs-operator">=</span>utf8;<br></code></pre></td></tr></table></figure>



<h1 id="10-消息幂等性保障"><a href="#10-消息幂等性保障" class="headerlink" title="10 消息幂等性保障"></a>10 <strong>消息幂等性保障</strong></h1><p>幂等性指一次和多次请求某一个资源,对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image138.gif?versionId=CAEQKRiBgMDT_6uA.hciIGMxZDY3N2JmYWE4MTQzYTA5MTMwN2I3NzI2YzJlMWNj" srcset="/img/loading.gif" lazyload alt="img"></p>
<p>在MQ中指,消费多条相同的消息,得到与消费该消息一次相同的结果。</p>
<h2 id="幂等性"><a href="#幂等性" class="headerlink" title="幂等性"></a>幂等性</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>用户对于同一操作发起的一次请求或者多次请求的结果是一致的，不会因为多次点击而产生了副作用。举个最简单的例子，那就是支付，用户购买商品后支付，支付扣款成功，但是返回结果的时候网络异常， 此时钱已经扣了，用户再次点击按钮，此时会进行第二次扣款，返回结果成功，用户查询余额发现多扣钱了，流水记录也变成了两条。在以前的单应用系统中，我们只需要把数据操作放入事务中即可，发生错误立即回滚，但是再响应客户端的时候也有可能出现网络中断或者异常等等</p>
<h3 id="消息重复消费"><a href="#消息重复消费" class="headerlink" title="消息重复消费"></a>消息重复消费</h3><p>消费者在消费 MQ 中的消息时，MQ 已把消息发送给消费者，消费者在给MQ 返回 ack 时网络中断， 故 MQ 未收到确认信息，该条消息会重新发给其他的消费者，或者在网络重连后再次发送给该消费者，但实际上该消费者已成功消费了该条消息，造成消费者消费了重复的消息。</p>
<h3 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h3><p>MQ 消费者的幂等性的解决一般使用全局 ID 或者写个唯一标识比如时间戳 或者 UUID 或者订单消费者消费 MQ 中的消息也可利用 MQ 的该 id 来判断，或者可按自己的规则生成一个全局唯一 id，每次消费消息时用该 id 先判断该消息是否已消费过。</p>
<h3 id="消费端的幂等性保障"><a href="#消费端的幂等性保障" class="headerlink" title="消费端的幂等性保障"></a>消费端的幂等性保障</h3><p>在海量订单生成的业务高峰期，生产端有可能就会重复发生了消息，这时候消费端就要实现幂等性， 这就意味着我们的消息永远不会被消费多次，即使我们收到了一样的消息。业界主流的幂等性有两种操作:a. 唯一 ID+指纹码机制,利用数据库主键去重, b.利用 redis 的原子性去实现</p>
<h3 id="唯一ID-指纹码机制"><a href="#唯一ID-指纹码机制" class="headerlink" title="唯一ID+指纹码机制"></a>唯一ID+指纹码机制</h3><p>指纹码:我们的一些规则或者时间戳加别的服务给到的唯一信息码,它并不一定是我们系统生成的，基本都是由我们的业务规则拼接而来，但是一定要保证唯一性，然后就利用查询语句进行判断这个 id 是否存在数据库中,优势就是实现简单就一个拼接，然后查询判断是否重复；劣势就是在高并发时，如果是单个数据库就会有写入性能瓶颈当然也可以采用分库分表提升性能，但也不是我们最推荐的方式。</p>
<h3 id="Redis-原子性"><a href="#Redis-原子性" class="headerlink" title="Redis 原子性"></a>Redis 原子性</h3><p>利用 redis 执行 setnx 命令，天然具有幂等性。从而实现不重复消费</p>
<h2 id="优先级队列"><a href="#优先级队列" class="headerlink" title="优先级队列"></a>优先级队列</h2><h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><p>在我们系统中有一个<strong>订单催付</strong>的场景，我们的客户在天猫下的订单,淘宝会及时将订单推送给我们，如果在用户设定的时间内未付款那么就会给用户推送一条短信提醒，很简单的一个功能对吧，但是，tmall 商家对我们来说，肯定是要分大客户和小客户的对吧，比如像苹果，小米这样大商家一年起码能给我们创造很大的利润，所以理应当然，他们的订单必须得到优先处理，而曾经我们的后端系统是使用 redis 来存</p>
<p>放的定时轮询，大家都知道 redis 只能用 List 做一个简简单单的消息队列，并不能实现一个优先级的场景，</p>
<p>所以订单量大了后采用 RabbitMQ 进行改造和优化,如果发现是大客户的订单给一个相对比较高的优先级， 否则就是默认优先级。</p>
<p><strong>消息幂等性保障</strong> <strong>乐观锁机制</strong></p>
<p>生产者发送消息：</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-attr">id</span>=<span class="hljs-string">1,money=500,version=1</span><br></code></pre></td></tr></table></figure>

<p>消费者接收消息</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-attr">id</span>=<span class="hljs-string">1,money=500,version=1</span><br><span class="hljs-attr">id</span>=<span class="hljs-string">1,money=500,version=1</span><br></code></pre></td></tr></table></figure>

<p>消费者需要保证幂等性：第一次执行SQL语句</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs mysql">第一次执行：version=1<br>update account set money = money - 500 , version = version + 1<br>where id = 1 and version = 1<br></code></pre></td></tr></table></figure>

<p>消费者需要保证幂等性：第二次执行SQL语句</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sql">第二次执行：version<span class="hljs-operator">=</span><span class="hljs-number">2</span><br>update account <span class="hljs-keyword">set</span> money <span class="hljs-operator">=</span> money <span class="hljs-operator">-</span> <span class="hljs-number">500</span> , version <span class="hljs-operator">=</span> version <span class="hljs-operator">+</span> <span class="hljs-number">1</span><br><span class="hljs-keyword">where</span> id <span class="hljs-operator">=</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> version <span class="hljs-operator">=</span> <span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>



<h1 id="11-RabbitMQ集群搭建"><a href="#11-RabbitMQ集群搭建" class="headerlink" title="11 RabbitMQ集群搭建"></a>11 RabbitMQ集群搭建</h1><p>摘要：实际生产应用中都会采用消息队列的集群方案，如果选择RabbitMQ那么有必要了解下它的集群方案原理</p>
<p>一般来说，如果只是为了学习RabbitMQ或者验证业务工程的正确性那么在本地环境或者测试环境上使用其单实例部署就可以了，但是出于MQ中间件本身的可靠性、并发性、吞吐量和消息堆积能力等问题的考虑，在生产环境上一般都会考虑使用RabbitMQ的集群方案。</p>
<h2 id="11-1-集群方案的原理"><a href="#11-1-集群方案的原理" class="headerlink" title="11.1 集群方案的原理"></a>11.1 集群方案的原理</h2><p>RabbitMQ这款消息队列中间件产品本身是基于Erlang编写，Erlang语言天生具备分布式特性（通过同步Erlang集群各节点的magic cookie来实现）。因此，RabbitMQ天然支持Clustering。这使得RabbitMQ本身不需要像ActiveMQ、Kafka那样通过ZooKeeper分别来实现HA方案和保存集群的元数据。集群是保证可靠性的一种方式，同时可以通过水平扩展以达到增加消息吞吐量能力的目的。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image140.gif?versionId=CAEQKRiBgMCN_quA.hciIGVhYmVkNmU4NGQ0ZTRhMmRhNDY2YzgzMmE0YzQzY2Yz" srcset="/img/loading.gif" lazyload alt="img"></p>
<h2 id="11-2-单机多实例部署"><a href="#11-2-单机多实例部署" class="headerlink" title="11.2 单机多实例部署"></a>11.2 单机多实例部署</h2><p>由于某些因素的限制，有时候你不得不在一台机器上去搭建一个rabbitmq集群，这个有点类似zookeeper的单机版。真实生成环境还是要配成多机集群的。有关怎么配置多机集群的可以参考其他的资料，这里主要论述如何在单机中配置多个rabbitmq实例。</p>
<p>主要参考官方文档：<a target="_blank" rel="noopener" href="https://www.rabbitmq.com/clustering.html">https://www.rabbitmq.com/clustering.html</a></p>
<p>首先确保RabbitMQ运行没有问题</p>
<figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs autoit">[root<span class="hljs-symbol">@atguigu</span> ~]<span class="hljs-meta"># systemctl start rabbitmq-server.service</span><br>[root<span class="hljs-symbol">@atguigu</span> ~]<span class="hljs-meta"># systemctl status rabbitmq-server.service</span><br></code></pre></td></tr></table></figure>

<p>停止rabbitmq服务</p>
<p>  <code>[root@atguigu ~]# systemctl stop rabbitmq-server.service</code>  </p>
<p>启动三个节点做集群演示：</p>
<p>由于web管理插件端口占用,所以还要指定其web插件占用的端口号。</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs routeros">[root@atguigu ~]# <span class="hljs-attribute">RABBITMQ_NODE_PORT</span>=5672 <span class="hljs-attribute">RABBITMQ_NODENAME</span>=rabbit1 <span class="hljs-attribute">RABBITMQ_SERVER_START_ARGS</span>=<span class="hljs-string">&quot;-rabbitmq_management listener [&#123;port,15672&#125;]&quot;</span>  rabbitmq-server -detached<br>[root@atguigu ~]# <span class="hljs-attribute">RABBITMQ_NODE_PORT</span>=5673 <span class="hljs-attribute">RABBITMQ_NODENAME</span>=rabbit2 <span class="hljs-attribute">RABBITMQ_SERVER_START_ARGS</span>=<span class="hljs-string">&quot;-rabbitmq_management listener [&#123;port,15673&#125;]&quot;</span>  rabbitmq-server -detached<br>[root@atguigu ~]# <span class="hljs-attribute">RABBITMQ_NODE_PORT</span>=5674 <span class="hljs-attribute">RABBITMQ_NODENAME</span>=rabbit3 <span class="hljs-attribute">RABBITMQ_SERVER_START_ARGS</span>=<span class="hljs-string">&quot;-rabbitmq_management listener [&#123;port,15674&#125;]&quot;</span>  rabbitmq-server -detached<br></code></pre></td></tr></table></figure>



<p>启动三个节点后，分别访问三个节点，后台管理页面，看看是否OK.</p>
<p>停止服务命令：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">1</span> stop<br><span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">2</span> stop<br><span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">3</span> stop<br></code></pre></td></tr></table></figure>



<p>rabbit1操作作为主节点：</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit1 stop_app  </span><br>Stopping <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit1</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit1 reset     </span><br>Resetting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit1</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit1 start_app</span><br>Starting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit1</span>@localhost ...<br></code></pre></td></tr></table></figure>



<p>rabbit2操作为从节点：</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit2 stop_app</span><br>Stopping <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit2</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit2 reset</span><br>Resetting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit2</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit2 join_cluster rabbit1</span><br>Clustering <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit2</span>@localhost with rabbit1 ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit2 start_app</span><br>Starting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit2</span>@localhost ...<br><br></code></pre></td></tr></table></figure>



<p>rabbit3操作为从节点：</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit3 stop_app</span><br>Stopping <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit3</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit3 reset</span><br>Resetting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit3</span>@localhost ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit3 join_cluster rabbit1</span><br>Clustering <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit3</span>@localhost with rabbit1@super ...<br>[root@atguigu ~]<span class="hljs-comment"># rabbitmqctl -n rabbit3 start_app</span><br>Starting <span class="hljs-keyword">node</span> <span class="hljs-title">rabbit3</span>@localhost ...<br></code></pre></td></tr></table></figure>



<p>查看集群状态：</p>
<figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs scss"><span class="hljs-selector-attr">[root@atguigu ~]</span># rabbitmqctl -n rabbit1 cluster_status<br>Cluster status of node rabbit1<span class="hljs-keyword">@localhost</span> ...<br>Basics<br> <br>Cluster <span class="hljs-attribute">name</span>: rabbit1<span class="hljs-keyword">@localhost</span><br> <br>Disk Nodes<br> <br>rabbit1<span class="hljs-keyword">@localhost</span><br>rabbit2<span class="hljs-keyword">@localhost</span><br>rabbit3<span class="hljs-keyword">@localhost</span><br> <br>Running Nodes<br> <br>rabbit1<span class="hljs-keyword">@localhost</span><br>rabbit2<span class="hljs-keyword">@localhost</span><br>rabbit3<span class="hljs-keyword">@localhost</span><br> <br>Versions<br> <br>rabbit1<span class="hljs-keyword">@localhost</span>: RabbitMQ <span class="hljs-number">3.8</span>.<span class="hljs-number">1</span> on Erlang <span class="hljs-number">21.3</span>.<span class="hljs-number">8.9</span><br>rabbit2<span class="hljs-keyword">@localhost</span>: RabbitMQ <span class="hljs-number">3.8</span>.<span class="hljs-number">1</span> on Erlang <span class="hljs-number">21.3</span>.<span class="hljs-number">8.9</span><br>rabbit3<span class="hljs-keyword">@localhost</span>: RabbitMQ <span class="hljs-number">3.8</span>.<span class="hljs-number">1</span> on Erlang <span class="hljs-number">21.3</span>.<span class="hljs-number">8.9</span><br>Alarms<br>(none)<br>Network Partitions<br>(none)<br>Listeners<br><span class="hljs-attribute">Node</span>: rabbit1<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">25672</span>, <span class="hljs-attribute">protocol</span>: clustering, <span class="hljs-attribute">purpose</span>: inter-node <span class="hljs-keyword">and</span> CLI tool communication<br><span class="hljs-attribute">Node</span>: rabbit1<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">5672</span>, <span class="hljs-attribute">protocol</span>: amqp, <span class="hljs-attribute">purpose</span>: AMQP <span class="hljs-number">0</span>-<span class="hljs-number">9</span>-<span class="hljs-number">1</span> <span class="hljs-keyword">and</span> AMQP <span class="hljs-number">1.0</span><br><span class="hljs-attribute">Node</span>: rabbit1<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">15672</span>, <span class="hljs-attribute">protocol</span>: http, <span class="hljs-attribute">purpose</span>: HTTP API<br><span class="hljs-attribute">Node</span>: rabbit2<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">25673</span>, <span class="hljs-attribute">protocol</span>: clustering, <span class="hljs-attribute">purpose</span>: inter-node <span class="hljs-keyword">and</span> CLI tool communication<br><span class="hljs-attribute">Node</span>: rabbit2<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">5673</span>, <span class="hljs-attribute">protocol</span>: amqp, <span class="hljs-attribute">purpose</span>: AMQP <span class="hljs-number">0</span>-<span class="hljs-number">9</span>-<span class="hljs-number">1</span> <span class="hljs-keyword">and</span> AMQP <span class="hljs-number">1.0</span><br><span class="hljs-attribute">Node</span>: rabbit2<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">15673</span>, <span class="hljs-attribute">protocol</span>: http, <span class="hljs-attribute">purpose</span>: HTTP API<br><span class="hljs-attribute">Node</span>: rabbit3<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">25674</span>, <span class="hljs-attribute">protocol</span>: clustering, <span class="hljs-attribute">purpose</span>: inter-node <span class="hljs-keyword">and</span> CLI tool communication<br><span class="hljs-attribute">Node</span>: rabbit3<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">5674</span>, <span class="hljs-attribute">protocol</span>: amqp, <span class="hljs-attribute">purpose</span>: AMQP <span class="hljs-number">0</span>-<span class="hljs-number">9</span>-<span class="hljs-number">1</span> <span class="hljs-keyword">and</span> AMQP <span class="hljs-number">1.0</span><br><span class="hljs-attribute">Node</span>: rabbit3<span class="hljs-keyword">@localhost</span>, <span class="hljs-attribute">interface</span>: [::], <span class="hljs-attribute">port</span>: <span class="hljs-number">15674</span>, <span class="hljs-attribute">protocol</span>: http, <span class="hljs-attribute">purpose</span>: HTTP API<br> <br>Feature flags<br> <br><span class="hljs-attribute">Flag</span>: drop_unroutable_metric, <span class="hljs-attribute">state</span>: enabled<br><span class="hljs-attribute">Flag</span>: empty_basic_get_metric, <span class="hljs-attribute">state</span>: enabled<br><span class="hljs-attribute">Flag</span>: implicit_default_bindings, <span class="hljs-attribute">state</span>: enabled<br><span class="hljs-attribute">Flag</span>: quorum_queue, <span class="hljs-attribute">state</span>: enabled<br><span class="hljs-attribute">Flag</span>: virtual_host_metadata, <span class="hljs-attribute">state</span>: enabled<br></code></pre></td></tr></table></figure>



<p>web监控：</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image142.jpg?versionId=CAEQKRiBgMD3_auA.hciIDFhMTNlNjI3MjdjNDQ5ZTlhNmQ1ZWViOThhZDg1ZDdi" srcset="/img/loading.gif" lazyload></p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs apache"> <span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">1</span> add_user admin admin<br><br><span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">1</span> set_user_tags admin administrator<br><br><span class="hljs-attribute">rabbitmqctl</span> -n rabbit<span class="hljs-number">1</span> change_password admin <span class="hljs-number">123456</span><br></code></pre></td></tr></table></figure>



<h2 id="11-3-集群管理（独立命令，了解即可）"><a href="#11-3-集群管理（独立命令，了解即可）" class="headerlink" title="11.3 集群管理（独立命令，了解即可）"></a>11.3 集群管理（独立命令，了解即可）</h2><p>rabbitmqctl join_cluster {cluster_node} [–ram]</p>
<p>将节点加入指定集群中。在这个命令执行前需要停止RabbitMQ应用并重置节点。</p>
<p>rabbitmqctl cluster_status</p>
<p>显示集群的状态。</p>
<p>rabbitmqctl change_cluster_node_type {disc|ram}</p>
<p>修改集群节点的类型。在这个命令执行前需要停止RabbitMQ应用。</p>
<p>rabbitmqctl forget_cluster_node [–offline]</p>
<p>将节点从集群中删除，允许离线执行。</p>
<p>rabbitmqctl update_cluster_nodes {clusternode}</p>
<p>在集群中的节点应用启动前咨询clusternode节点的最新信息，并更新相应的集群信息。这个和join_cluster不同，它不加入集群。考虑这样一种情况，节点A和节点B都在集群中，当节点A离线了，节点C又和节点B组成了一个集群，然后节点B又离开了集群，当A醒来的时候，它会尝试联系节点B，但是这样会失败，因为节点B已经不在集群中了。rabbitmqctl update_cluster_nodes -n A C可以解决这种场景。</p>
<p>rabbitmqctl cancel_sync_queue [-p vhost] {queue}</p>
<p>取消队列queue同步镜像的操作。</p>
<p>rabbitmqctl set_cluster_name {name}</p>
<p>设置集群名称。集群名称在客户端连接时会通报给客户端。Federation和Shovel插件也会有用到集群名称的地方。集群名称默认是集群中第一个节点的名称，通过这个命令可以重新设置。</p>
<h2 id="11-4-RabbitMQ镜像集群配置"><a href="#11-4-RabbitMQ镜像集群配置" class="headerlink" title="11.4 RabbitMQ镜像集群配置"></a>11.4 RabbitMQ镜像集群配置</h2><p>上面已经完成RabbitMQ默认集群模式，但并不保证队列的高可用性，尽管交换机、绑定这些可以复制到集群里的任何一个节点，但是队列内容不会复制。虽然该模式解决一项目组节点压力，但队列节点宕机直接导致该队列无法应用，只能等待重启，所以要想在队列节点宕机或故障也能正常应用，就要复制队列内容到集群里的每个节点，必须要创建镜像队列。</p>
<p>镜像队列是基于普通的集群模式的，然后再添加一些策略，所以你还是得先配置普通集群，然后才能设置镜像队列，我们就以上面的集群接着做。</p>
<p>设置的镜像队列可以通过开启的网页的管理端Admin-&gt;Policies，也可以通过命令。</p>
<p>·     Name:策略名称</p>
<p>·     Pattern：匹配的规则，如果是匹配所有的队列，是^.</p>
<p>·     Definition:使用ha-mode模式中的all，也就是同步所有匹配的队列。问号链接帮助文档。</p>
<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image146.jpg?versionId=CAEQKRiBgMDl_auA.hciIDY4ZDlkNzU4NmUzMzRhMmJiYWM0ZjgwOTc5MTNiYjBj" srcset="/img/loading.gif" lazyload></p>
<h2 id="11-5-负载均衡-HAProxy"><a href="#11-5-负载均衡-HAProxy" class="headerlink" title="11.5 负载均衡-HAProxy"></a>11.5 负载均衡-HAProxy</h2><p>HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理，支持虚拟主机，它是免费、快速并且可靠的一种解决方案,包括Twitter，Reddit，StackOverflow，GitHub在内的多家知名互联网公司在使用。HAProxy实现了一种事件驱动、单一进程模型，此模型支持非常大的并发连接数。</p>
<p><a target="_blank" rel="noopener" href="https://www.haproxy.org/">https://www.haproxy.org/</a></p>
<h3 id="11-5-1-安装HAProxy"><a href="#11-5-1-安装HAProxy" class="headerlink" title="11.5.1 安装HAProxy"></a>11.5.1 安装HAProxy</h3><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span>下载依赖包 <br>yum install gcc vim wget  <br><span class="hljs-regexp">//</span>上传haproxy源码包; -C解压到指定的目录  <br>tar -zxvf haproxy-<span class="hljs-number">2.3</span>.<span class="hljs-number">14</span>.tar.gz -C <span class="hljs-regexp">/usr/</span>local  <br><span class="hljs-regexp">//</span>进入目录、进行编译、安装  <br>cd <span class="hljs-regexp">/usr/</span>local/haproxy-<span class="hljs-number">2.3</span>.<span class="hljs-number">14</span>  <br><span class="hljs-regexp">//</span> make 表示编译；TARGET=linux31 表示CentOS7系统；<br>PREFIX=<span class="hljs-regexp">/usr/</span>local/haproxy指定安装路径  <br><span class="hljs-regexp">//</span> TARGET=linux310，内核版本，使用uname -r查看内核，如：<span class="hljs-number">3.10</span>.<span class="hljs-number">0</span>-<span class="hljs-number">514</span>.el7，此时该参数就为linux310；  <br>make TARGET=linux310 PREFIX=<span class="hljs-regexp">/usr/</span>local/haproxy  <br>make install PREFIX=<span class="hljs-regexp">/usr/</span>local/haproxy  <br>mkdir <span class="hljs-regexp">/etc/</span>haproxy  <br><span class="hljs-regexp">//</span>添加用户组：-r 创建一个系统组；-g 组ID  <br>groupadd -r -g <span class="hljs-number">149</span> haproxy  <br><span class="hljs-regexp">//</span>添加用户：-g 新账户组的名称；-r 创建一个系统用户；-s 新用户的登录shell; -u 新账户的用户ID  <br>useradd -g haproxy -r -s <span class="hljs-regexp">/sbin/</span>nologin -u <span class="hljs-number">149</span> haproxy  <br><span class="hljs-regexp">//</span>创建haproxy配置文件  <br>vim <span class="hljs-regexp">/etc/</span>haproxy/haproxy.cfg  <br></code></pre></td></tr></table></figure>



<h3 id="11-5-2-配置HAProxy"><a href="#11-5-2-配置HAProxy" class="headerlink" title="11.5.2 配置HAProxy"></a>11.5.2 配置HAProxy</h3><p>配置文件路径：/etc/haproxy/haproxy.cfg</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-comment">#全局配置</span><br><span class="hljs-attribute">global</span><br>    <span class="hljs-comment">#日志输出配置，所有日志都记录在本机，通过local0输出</span><br>    <span class="hljs-attribute">log</span> <span class="hljs-number">127.0.0.1</span> local<span class="hljs-number">0</span> info<br>    <span class="hljs-comment">#最大连接数</span><br>    <span class="hljs-attribute">maxconn</span> <span class="hljs-number">5120</span><br>    <span class="hljs-comment">#改变当前的工作目录</span><br>    <span class="hljs-attribute">chroot</span> /usr/local/haproxy<br>    <span class="hljs-comment">#以指定的UID运行haproxy进程</span><br>    <span class="hljs-attribute">uid</span> <span class="hljs-number">99</span><br>    <span class="hljs-comment">#以指定的GID运行haproxy进程</span><br>    <span class="hljs-attribute">gid</span> <span class="hljs-number">99</span><br>    <span class="hljs-comment">#以守护进程方式运行haproxy</span><br>    <span class="hljs-attribute">daemon</span><br>    <span class="hljs-attribute">quiet</span><br>    <span class="hljs-attribute">nbproc</span> <span class="hljs-number">20</span><br>    <span class="hljs-comment">#当前进程PID文件</span><br>    <span class="hljs-attribute">pidfile</span> /var/run/haproxy.pid<br><span class="hljs-comment">#默认配置</span><br><span class="hljs-attribute">defaults</span><br>    <span class="hljs-comment">#应用全局的日志配置</span><br>    <span class="hljs-attribute">log</span> global<br>    <span class="hljs-comment">#默认的模式mode&#123;tcp|http|health&#125;</span><br>    <span class="hljs-attribute">mode</span> tcp<br>    <span class="hljs-comment">#日志类别</span><br>    <span class="hljs-attribute">option</span> tcplog<br>    <span class="hljs-comment">#不记录检查检查日志信息</span><br>    <span class="hljs-attribute">option</span> dontlognull<br>    <span class="hljs-comment">#3次失败则认为服务不可用</span><br>    <span class="hljs-attribute">retries</span> <span class="hljs-number">3</span><br>    <span class="hljs-attribute">option</span> redispatch<br>    <span class="hljs-comment">#每个进程可用的最大连接数</span><br>    <span class="hljs-attribute">maxconn</span> <span class="hljs-number">2000</span>   <br><span class="hljs-comment">#绑定配置</span><br><span class="hljs-attribute"><span class="hljs-nomarkup">listen</span></span> rabbitmq_cluster<br>    <span class="hljs-attribute">bind</span> *:<span class="hljs-number">5677</span><br>    <span class="hljs-comment">#配置TCP模式</span><br>    <span class="hljs-attribute">mode</span> tcp<br>    <span class="hljs-comment">#balance url_param userid</span><br>    <span class="hljs-comment">#balance url_param session_id check_post 64</span><br>    <span class="hljs-comment">#balance hdr(User-Agent)</span><br>    <span class="hljs-comment">#balance hdr(host)</span><br>    <span class="hljs-comment">#balance hdr(Host) use_domain_only</span><br>    <span class="hljs-comment">#balance rdp-cookie</span><br>    <span class="hljs-comment">#balance leastconn</span><br>    <span class="hljs-comment">#balance source //ip</span><br>    <span class="hljs-comment">#简单的轮询</span><br>    <span class="hljs-attribute">balance</span> roundrobin<br>    <span class="hljs-comment">#server rabbit1 定义服务内部标识，</span><br>    <span class="hljs-comment">#127.0.0.1:5672 服务连接IP和端口，</span><br>    <span class="hljs-comment">#check inter 5000 定义每隔多少毫秒检查服务是否可用，</span><br>    <span class="hljs-comment">#rise 2 服务故障后需要多少次检查才能被再次确认可用，</span><br>    <span class="hljs-comment">#fall 2 经历多次失败的检查检查后，haproxy才会停止使用此服务</span><br>    <span class="hljs-comment">#weight 1 定义服务权重</span><br>    <span class="hljs-attribute">server</span> rabbit<span class="hljs-number">1</span> <span class="hljs-number">192.168.137.118:5672</span> check inter <span class="hljs-number">5000</span> rise <span class="hljs-number">2</span> fall <span class="hljs-number">2</span> weight <span class="hljs-number">1</span><br>    <span class="hljs-attribute">server</span> rabbit<span class="hljs-number">2</span> <span class="hljs-number">192.168.137.118:5673</span> check inter <span class="hljs-number">5000</span> rise <span class="hljs-number">2</span> fall <span class="hljs-number">2</span> weight <span class="hljs-number">1</span><br>    <span class="hljs-attribute">server</span> rabbit<span class="hljs-number">3</span> <span class="hljs-number">192.168.137.118:5674</span> check inter <span class="hljs-number">5000</span> rise <span class="hljs-number">2</span> fall <span class="hljs-number">2</span> weight <span class="hljs-number">1</span><br><span class="hljs-comment">#haproxy监控页面地址</span><br><span class="hljs-attribute"><span class="hljs-nomarkup">listen</span></span> stats<br>    <span class="hljs-attribute">bind</span> <span class="hljs-number">192.168.137.118:8100</span><br>    <span class="hljs-attribute">mode</span> http<br>    <span class="hljs-attribute">option</span> httplog<br>    <span class="hljs-attribute">stats</span> enable<br>    <span class="hljs-attribute">stats</span> uri /rabbitmq-stats<br>    <span class="hljs-attribute">stats</span> refresh <span class="hljs-number">5</span>s<br><br></code></pre></td></tr></table></figure>



<p>启动HAproxy负载</p>
<p>  <code>/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg</code>  </p>
<p>//查看haproxy进程状态</p>
<p>  <code>ps -ef | grep haproxy</code>  </p>
<p>访问如下地址对mq节点进行监控</p>
<p><a target="_blank" rel="noopener" href="http://192.168.137.130:8100/rabbitmq-stats">http://192.168.137.118:8100/rabbitmq-stats</a></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-string">springboot</span> <span class="hljs-string">yml文件中访问mq集群地址：</span><br><span class="hljs-attr">spring:</span> <br>  <span class="hljs-attr">rabbitmq:</span> <br>    <span class="hljs-attr">host:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.137</span><span class="hljs-number">.118</span><br>    <span class="hljs-attr">port:</span> <span class="hljs-number">5677</span><br>    <span class="hljs-attr">username:</span> <span class="hljs-string">admin</span><br>    <span class="hljs-attr">password:</span> <span class="hljs-number">123456</span><br><span class="hljs-attr">virtual-host:</span> <span class="hljs-string">/</span><br><span class="hljs-comment">#addresses: 192.168.137.118:5672,192.168.137.118:5673,192.168.137.118:5674</span><br></code></pre></td></tr></table></figure>

<p><img src="https://lllong.oss-cn-shenzhen.aliyuncs.com/RabbitMQ/clip_image148.jpg?versionId=CAEQKRiBgICK_quA.hciIGIyMDJlODgyYjlkNTQwOTQ4YWUxYTYwNjc0MmZkNzc3" srcset="/img/loading.gif" lazyload alt="img"></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/RabbitMQ/">RabbitMQ</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/RabbitMQ/">RabbitMQ</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客目前大部分文章都是参考尚硅谷或者马士兵教育的学习资料！<a href="http://www.atguigu.com/" rel="nofollow noopener"官网地址！</a> 
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/03/06/JVM/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">JVM学习笔记整理</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/02/18/nacosCluster/">
                        <span class="hidden-mobile">Linux环境搭建Nacos集群</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">

  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
	<!--《添加网站运行时间 -->
<br/>

<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
var now = new Date(); 

function createtime() {
    //此处修改你的建站时间或者网站上线时间
    var grt = new Date('11/02/2021 21:39:00');
    now.setTime(now.getTime() + 250);
    days = (now - grt) / 1000 / 60 / 60 / 24;

    dnum = Math.floor(days);
    hours = (now - grt) / 1000 / 60 / 60 - (24 * dnum);
    hnum = Math.floor(hours);
    if (String(hnum).length == 1) {
        hnum = "0" + hnum;
    }
    minutes = (now - grt) / 1000 / 60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes);
    if (String(mnum).length == 1) {
        mnum = "0" + mnum;
    }
    seconds = (now - grt) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds);
    if (String(snum).length == 1) {
        snum = "0" + snum;
    }
    document.getElementById("timeDate").innerHTML = " 本站已各种夹缝中安全运行 " + dnum + " 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250);
</script>

<!-- 添加网站运行时间》-->
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
